Skip to content

方法

什么是方法?

在 Java 中,方法(Method)是类中定义的一段代码块,用于执行特定的功能或任务。它是程序中可重复使用的逻辑单元,通常用来完成某个操作或返回某个计算结果。方法是面向对象编程中实现封装和模块化的重要手段。

方法的特点

  • 可重用性:方法可以在程序中多次调用,避免代码重复。
  • 模块化:将复杂逻辑拆分成小块,便于维护和理解。
  • 封装性:通过访问修饰符(如 publicprivate)控制方法的可访问范围,保护数据安全。

方法的定义

方法的定义通常包含以下部分:

java
修饰符 返回值类型 方法名(参数列表) {
    // 方法体:执行的代码逻辑
    return 返回值; // 如果返回值类型不是 void,则需要返回相应的值
}

组成说明:

  • 修饰符:如 publicprivatestatic 等,控制方法的访问权限和行为。
    • public:方法可被任意类访问。
    • private:方法仅在定义的类内部可访问。
    • static:表示方法属于类而非实例,无需创建对象即可调用。
  • 返回值类型:方法执行后返回的数据类型,如 intStringvoid(无返回值)。
  • 方法名:遵循命名规范,通常以动词开头,使用小驼峰命名法(如 calculateSum)。
  • 参数列表:方法接收的输入参数,可以为空或包含多个参数,格式为 (类型 参数名, 类型 参数名, ...)
  • 方法体:方法的实际逻辑代码。
  • return 语句:如果方法有返回值,必须使用 return 返回指定类型的值;void 方法可以省略 return 或使用空 return;

示例代码

以下是一个计算两个int类型的和的方法:

java
/**
 * 求两个int类型的和
 * @param a 参数a
 * @param b 参数b
 * @return 结果
 */
public int add(int a, int b) {
    return a + b;
}

方法的分类

成员方法

成员方法又称实例方法,是类的一个成员,属于类的对象,可以通过对象来调用。

示例:

java
public class Calculator {
    public static void main(String[] args) {
        // 创建一个Calculator对象
        Calculator calc = new Calculator();
        // 调用成员方法
        int result = calc.subtract(10, 5);
        System.out.println(result);
    }

    // 成员方法
    public int subtract(int a, int b) {
        return a - b;
    }
}

静态方法

使用 static 关键字修饰的方法,称为静态方法,属于类的方法,可以通过类名来调用,不需要创建对象。常用于工具类或不依赖实例状态的操作。

示例:

java
public class MathUtils {
    public static void main(String[] args) {
        // 不需要创建对象,直接通过类名称调用
        int result = MathUtils.multiply(4, 5);
        System.out.println(result);
    }

    // 静态方法
    public static int multiply(int a, int b) {
        return a * b;
    }
}

构造方法

构造方法又称构造函数,是类的一个特殊的方法,用于创建和初始化对象的状态,方法名与类名相同,无返回值类型。自动在对象创建时调用(使用 new 关键字)。

示例:

java
public class Main {
    public static void main(String[] args) {
        // 创建 Student 对象
        Student student = new Student("张三", 18);
        // 没有重写toString()方法所以显示method.Student@30f39991
        System.out.println(student);
    }
}

// Student 类
class Student {
    // 成员变量
    String name;
    Integer age;

    // 构造方法
    Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}

方法的调用

调用方式

成员方法(实例方法):通过对象实例调用,格式为 对象名.方法名(参数列表)

静态方法(类方法):通过类名调用,格式为 类名.方法名(参数列表)

构造方法:使用 new 关键字创建对象,格式为 new 类名(参数列表)

示例:

java
public class Main {
    public static void main(String[] args) {
        // new关键字调用构造方法创建Example类的对象实例
        Example e = new Example("haha");
        e.instanceMethod(); // 输出:这是一个成员(实例)方法
        Example.staticMethod(); // 输出:这是一个静态方法
    }
}

// Example 类
class Example {

    // 成员变量
    String msg;

    // 空参数的构造方法
    public Example() {
    }

    // 有参数的构造方法
    public Example(String m) {
        this.msg = m;
    }

    // 成员方法
    public void instanceMethod() {
        System.out.println("这是一个成员(实例)方法");
    }

    // 静态方法
    public static void staticMethod() {
        System.out.println("这是一个静态方法");
    }
}

形参和实参

形参(形式参数):方法定义时的参数,用于接收方法调用时传递的实参。

实参(实际参数):方法调用时传递的参数,用于替换形参的值。

示例:

java
public class Main {
    public static void main(String[] args) {
        // 调用方法时传递的10和5是实参
        int result = add(10, 5);
        System.out.println(result);
    }

    // 方法定义的参数a和b是形参
    public static int add(int a, int b) {
        return a + b;
    }
}

参数传递

Java方法的参数传递只有一种方式:值传递

  • 对于基本数据类型(如 intdouble):传递的是值的副本,方法内的修改不影响原值。
  • 对于引用类型(如对象、数组):传递的是引用地址的副本,方法内可修改对象的属性,但不能改变原引用指向的对象。

示例:

java
public class Main {
    public static void main(String[] args) {
        int a = 1; // 变量 a 在 main 方法的栈帧中,存储的值就是 1
        int b = 2; // 变量 b 在 main 方法的栈帧中,存储的值就是 2

        test1(a, b); // 调用 test1 方法

        // ... a 的值仍然是 1, b 的值仍然是 2
    }

    public static void test1(int a, int b) { // 注意:这里的 a 和 b 是 test1 方法的局部变量
        // 当调用 test1(a, b) 时,发生了以下事情:
        // 1. 在 test1 方法的栈帧中,创建了新的局部变量 a 和 b。
        // 2. 将 main 方法中 a 的值 (1) 复制一份,赋给 test1 的变量 a。
        // 3. 将 main 方法中 b 的值 (2) 复制一份,赋给 test1 的变量 b。

        // 所以,此时存在两套 a 和 b,它们互不相干。

        a = 100; // 这里修改的是 test1 方法栈帧中的 a,和 main 方法中的 a 没有任何关系。
        b = 200; // 同理,修改的是 test1 方法中的 b。
    }
}
java
public class Main {
    public static void main(String[] args) {
        // 1. new int[]{1, 2, 3, 4, 5} 在堆内存中创建了一个数组对象。
        //    假设这个对象在内存中的地址是 0x123ABC。
        // 2. int[] arr; 创建了一个引用变量 arr。
        // 3. arr = ...; 将数组对象的地址 0x123ABC 赋值给了 arr。
        //    所以,arr 变量中存储的“值”是 0x123ABC。
        int[] arr = new int[]{1, 2, 3, 4, 5};

        test1(arr); // 调用 test1 方法
    }

    public static void test1(int[] array) { // 注意:这里的 array 是 test1 方法的局部变量
        // 当调用 test1(arr) 时,发生了什么?
        // 同样是值传递!
        // 1. 在 test1 方法的栈帧中,创建了新的局部变量 array。
        // 2. 将 main 方法中 arr 的“值” (也就是地址 0x123ABC) 复制一份,赋给 test1 的变量 array。

        // 现在,main 方法中的 arr 和 test1 方法中的 array,它们的值都是 0x123ABC。
        // 这意味着它们都指向了堆内存中同一个数组对象。
        // 就像你把房子的钥匙复制了一把给朋友,你们俩的钥匙都能打开同一扇门。

        // 将第一个元素改成999
        array[0] = 999;
        // 这行代码的含义是:
        // 1. 通过 array 变量中存储的地址 (0x123ABC) 找到堆内存中的数组对象。
        // 2. 修改这个数组对象的第一个元素为 999。

        // 因为 arr 和 array 指向的是同一个对象,所以当 test1 执行完毕后,
        // 回到 main 方法,通过 arr 去查看那个数组对象时,会发现它已经被修改了。
    }
}

方法重载

方法重载允许在同一类中定义多个同名方法,但参数列表(参数数量或类型)必须不同。Java 会根据调用时的参数类型和数量选择合适的方法。

方法重载的规则:

  • 方法名必须相同。
  • 参数列表不同(数量或者类型)。
  • 返回值类型、修饰符不影响重载。

示例:

java
public class Printer {
    public static void main(String[] args) {
        // 调用方法
        Printer printer = new Printer();
        printer.print("Hello");        // 输出: String: Hello
        printer.print(42);            // 输出: Integer: 42
        printer.print("Test", 100);   // 输出: String and Integer: Test, 100
    }

    public void print(String s) {
        System.out.println("String: " + s);
    }

    public void print(int i) {
        System.out.println("Integer: " + i);
    }

    public void print(String s, int i) {
        System.out.println("String and Integer: " + s + ", " + i);
    }
}

注意事项

  • 命名规范:方法名应使用小驼峰命名法,清晰表达功能,如 calculateArea、sendMessage。
  • 单一职责:一个方法尽量只完成一个功能,避免逻辑过于复杂。
  • 参数设计:避免过多参数,通常不超过 4 个;若参数过多,考虑使用对象封装。
  • 异常处理:方法可能抛出异常,需使用 throws 声明或 try-catch 处理。
  • 性能优化:避免在方法中执行过多计算或资源密集型操作,必要时优化算法。

参考资料

根据 MIT 许可证发布