Java 方法全面解析

1. 方法签名各部分示例

方法签名包含多个部分,以下是各部分的示例:
| 签名部分 | 示例 |
| ---- | ---- |
| 修饰符 | public, private, protected, package - private(未指定修饰符) |
| 返回类型 | int(也可使用任何 Java 基本类型,如 boolean、float、long,或任何预定义引用类型,如 String 和类类型) |
| 方法名 | addContact, setCoordinates, addAToB |
| 参数 | (boolean isFriend, String name), (int x, int y), (int a, int b) |

修饰符用于指定哪些代码可以使用(调用)你的方法,变量也可以有修饰符。例如:

// 大多数代码可以访问我
public int a;
// 其他类中的代码无法访问我
private String secret = "Shhh! I am private";

不过,修饰符并非学习的必要条件,但在后续的面向对象编程学习中会很重要。

2. 返回类型

返回类型是可选的。例如:

int addAToB(int a, int b){
    int answer = a + b;
    return answer;
}

此方法的返回类型是 int,它会将计算结果返回给调用它的代码。

方法也可以不返回值,此时签名中必须使用 void 关键字作为返回类型,且方法体中不能尝试返回值,否则会导致编译错误,但可以使用无值的 return 关键字。以下是一些有效组合:

void doSomething(){
    // 代码
    // 无需返回
}
void doSomethingElse(){
    // 代码
    return;
}
void doYetAnotherThing(){
    // 一些代码
    if(someCondition){
        return;
    }
    // 更多可能执行或不执行的代码
    return;
}
String joinTogether(String firstName, String lastName){
    return firstName + lastName;
}

可以按如下方式调用这些方法:

// 调用方法
doSomething();
doSomethingElse();
doYetAnotherThing();
String fullName = joinTogether("Alan ", "Turing");
// fullName 现在为 "Alan Turing"
3. 方法名

设计自己的方法时,方法名可以任意,但通常使用能清晰说明方法功能的动词,并且遵循驼峰命名法,即第一个单词的首字母小写,后续单词的首字母大写。例如:

XGHHY78802c(){
    // 代码
}

此方法合法但不清晰,更清晰的示例如下:

doSomeVerySpecificTask(){
    // 代码
}
getMyFriendsList(){
    // 代码
}
startNewMessage(){
    // 代码
}
4. 参数

参数允许我们将调用代码中的数据值共享给方法。例如:

int addAToB(int a, int b){
    int answer = a + b;
    return answer;
}

参数包含在方法名后面的括号中。调用方法时,参数会被初始化,如:

int returnedAnswer = addAToB(10, 5);

参数可以使用任何 Java 类型,包括自定义类型,也可以混合使用不同类型,并且可以根据需要使用多个参数。例如:

void addToAddressBook(char firstInitial, String lastName, String city, int age){
    // 所有参数现在都是已声明和初始化的变量
    // 这里是将详细信息添加到地址簿的代码
}
5. 方法体

方法体可以使用我们目前所学的任何 Java 语法,实际上,我们之前编写的所有代码都在方法中。

6. 使用方法的演示应用

我们将构建两个应用来进一步探索方法:
- 真实世界方法应用
1. 创建一个名为 Real World Methods 的新 Android 项目,使用 Empty Activity,其他设置保持默认。
2. 切换到 MainActivity.java 文件,在 onCreate 方法的右花括号 } 之后添加以下三个方法:

String joinThese(String a, String b, String c){
    return a + b + c;
}
float getAreaCircle(float radius){
    return 3.141f * radius * radius;
}
void changeA(int a){
    a++;
}
3. 在 onCreate 方法中调用 setContentView 之后添加以下代码:
String joinedString = joinThese("Methods ", "are ", "cool ");
Log.e("joinedString = ", "" + joinedString);
float area = getAreaCircle(5f);
Log.e("area = ", "" + area);
int a = 0;
changeA(a);
Log.e("a = ", "" + a);

运行应用后,logcat 输出如下:

joinedString =﹕ Methods are cool
area =﹕ 78.525
a =﹕ 0

可以发现,当我们将 a 传递给 changeA 方法时,实际上传递的是 a 中存储的值,而不是变量 a 本身,这在 Java 中称为按值传递。变量的作用域仅限于声明它的方法。

  • 探索方法重载应用
    1. 创建一个名为 Exploring Method Overloading 的新 Empty Activity 项目。
    2. 在 onCreate 方法的右花括号 } 之后,但在 MainActivity 的右花括号 } 之前添加以下三个方法:
void printStuff(int myInt){
    Log.i("info", "This is the int only version");
    Log.i("info", "myInt = " + myInt);
}
void printStuff(String myString){
    Log.i("info", "This is the String only version");
    Log.i("info", "myString = " + myString);
}
void printStuff(int myInt, String myString){
    Log.i("info", "This is the combined int and String version");
    Log.i("info", "myInt = " + myInt);
    Log.i("info", "myString = " + myString);
}
3. 在 onCreate 方法的右花括号 } 之前添加以下代码:
int anInt = 10;
String aString = "I am a string";
printStuff(anInt);
printStuff(aString);
printStuff(anInt, aString);

运行应用后,控制台输出如下:

info﹕ This is the int only version
info﹕ myInt = 10
info﹕ This is the String only version
info﹕ myString = I am a string
info﹕ This is the combined int and String version
info﹕ myInt = 10
info﹕ myString = I am a string

Java 将具有相同名称但不同参数的方法视为不同的方法,这称为方法重载。

7. 方法重载与重写的区别
  • 重载:有多个名称相同但参数不同的方法。
  • 重写:用相同名称和相同参数列表的方法替换原方法。
8. 作用域和变量回顾

在一个方法中声明的变量只能在该方法中可见。例如,在 onCreate 方法中声明的变量 a,在 onPause 或其他方法中无法使用。

类可以有自己的变量,称为成员变量或字段,它们具有类作用域,类中的所有方法都可以访问和使用它们。声明成员变量时,在类的开始处、任何方法之外使用常规语法即可。例如:

public class MainActivity extends AppCompatActivity {
    int mSomeVariable = 0;
    // 其余代码和方法按常规方式编写
}

我们在变量名前加 m 只是为了提醒自己这是一个成员变量。

9. 常见问题解答
  • 问题 :以下方法定义有什么问题?
doSomething(){
    // 在这里做某事
}

答案 :未声明返回类型。方法可以不返回值,但此时返回类型必须为 void。正确的方法如下:

void doSomething(){
    // 在这里做某事
}
  • 问题 :以下方法定义有什么问题?
float getBalance(){
    String customerName = "Linus Torvalds";
    float balance = 429.66f;
    return userName;
}

答案 :代码中存在拼写错误,返回的变量 userName 未定义,可能是想返回 balance 变量。同时,方法声明的返回类型是 float,但如果使用 userName(假设是想返回 customerName),则返回类型不匹配。

Java 方法全面解析

10. 变量作用域的深入理解

变量作用域是 Java 中一个重要的概念,它决定了变量的可见性和生命周期。为了更清晰地理解,我们可以通过一个 mermaid 流程图来展示变量作用域的规则:

graph TD;
    A[声明变量] --> B{变量声明位置};
    B -->|方法内| C[方法作用域];
    B -->|类内方法外| D[类作用域];
    C --> E{是否在嵌套块内};
    E -->|是| F[嵌套块作用域];
    E -->|否| G[方法整体作用域];
    D --> H[类内所有方法可访问];
    F --> I[仅嵌套块内可访问];
    G --> J[仅声明方法内可访问];

从这个流程图可以看出,变量的作用域主要分为方法作用域和类作用域。在方法作用域中,如果存在嵌套块,还会有嵌套块作用域。

例如,下面的代码展示了不同作用域的变量:

public class ScopeExample {
    // 类作用域的成员变量
    int classVariable = 10;

    public void method1() {
        // 方法作用域的局部变量
        int methodVariable = 20;
        if (methodVariable > 10) {
            // 嵌套块作用域的局部变量
            int blockVariable = 30;
            System.out.println("Block variable: " + blockVariable);
        }
        // 下面这行代码会报错,因为 blockVariable 超出了作用域
        // System.out.println("Block variable: " + blockVariable);
        System.out.println("Method variable: " + methodVariable);
    }

    public void method2() {
        // 可以访问类作用域的成员变量
        System.out.println("Class variable: " + classVariable);
        // 下面这行代码会报错,因为 methodVariable 是 method1 方法的局部变量
        // System.out.println("Method variable: " + methodVariable);
    }
}

在这个例子中, classVariable 是类作用域的成员变量, methodVariable method1 方法作用域的局部变量, blockVariable if 嵌套块作用域的局部变量。不同作用域的变量有不同的可见性和生命周期。

11. 方法重载的应用场景

方法重载在实际编程中有很多应用场景,以下是一些常见的情况:
- 处理不同类型的数据 :当需要对不同类型的数据执行相似的操作时,可以使用方法重载。例如,计算不同类型数据的绝对值:

public class AbsoluteValue {
    public int abs(int num) {
        return num < 0 ? -num : num;
    }

    public double abs(double num) {
        return num < 0 ? -num : num;
    }
}

在这个例子中, abs 方法被重载,分别处理 int double 类型的数据。

  • 提供不同的参数组合 :根据不同的需求,提供不同参数组合的方法。例如,创建一个 Rectangle 类,计算矩形的面积:
public class Rectangle {
    public int area(int length) {
        // 假设是正方形,边长为 length
        return length * length;
    }

    public int area(int length, int width) {
        return length * width;
    }
}

在这个例子中, area 方法被重载,一个方法接受一个参数(用于计算正方形面积),另一个方法接受两个参数(用于计算矩形面积)。

12. 方法设计的最佳实践

在设计 Java 方法时,遵循一些最佳实践可以提高代码的可读性、可维护性和可扩展性。以下是一些建议:
- 单一职责原则 :一个方法应该只做一件事情,并且把这件事情做好。例如,一个方法只负责计算面积,另一个方法只负责打印结果。

public class AreaCalculator {
    public double calculateCircleArea(double radius) {
        return 3.141 * radius * radius;
    }

    public void printArea(double area) {
        System.out.println("The area is: " + area);
    }
}

在这个例子中, calculateCircleArea 方法只负责计算圆的面积, printArea 方法只负责打印面积结果。

  • 使用有意义的方法名 :方法名应该能够清晰地表达方法的功能。例如, getUserInfo 方法比 getData 方法更能明确其功能。

  • 合理使用参数和返回值 :参数应该是方法执行所需的必要数据,返回值应该是方法执行的结果。避免方法有过多的参数或复杂的返回值。

13. 总结

通过对 Java 方法的学习,我们了解了方法签名的各个部分,包括修饰符、返回类型、方法名和参数。掌握了返回类型的使用,包括 void 类型和具体类型的返回。学会了如何设计有意义的方法名和合理使用参数。

同时,我们还通过实际的演示应用,深入理解了变量作用域、方法重载和重写的概念。变量作用域决定了变量的可见性和生命周期,方法重载允许我们使用相同的方法名处理不同的参数组合,方法重写则用于替换父类的方法。

在实际编程中,遵循方法设计的最佳实践可以提高代码的质量和可维护性。希望通过这些知识的学习,能够帮助你更好地编写 Java 代码。

最后,通过以下表格总结 Java 方法的关键知识点:
| 知识点 | 描述 |
| ---- | ---- |
| 方法签名 | 包含修饰符、返回类型、方法名和参数 |
| 返回类型 | 可以是具体类型或 void |
| 方法名 | 遵循驼峰命名法,表达方法功能 |
| 参数 | 可以是任何 Java 类型,用于传递数据 |
| 方法体 | 使用 Java 语法实现方法功能 |
| 变量作用域 | 分为方法作用域和类作用域 |
| 方法重载 | 多个同名方法,参数不同 |
| 方法重写 | 替换同名同参数列表的方法 |
| 最佳实践 | 单一职责、有意义的方法名、合理使用参数和返回值 |

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐