Java 方法

当你在多处写同样的代码,就该把它抽成方法(Function/Method)。方法是"代码复用"的基本单元——给它输入,它返回输出。本章带你掌握 Java 方法的定义、调用、参数传递、重载、可变参数和递归。

1. 方法定义与调用

Java 方法定义的格式:修饰符 返回类型 方法名(参数列表) { 方法体 }。所有方法必须定义在类内部。

public class MethodDemo {

    // 方法定义格式:
    // 修饰符 返回类型 方法名(参数列表) { 方法体 }
    public static int add(int a, int b) {
        return a + b;          // 返回 int
    }

    // 无返回值用 void,不需要 return
    public static void greet(String name) {
        System.out.println("你好, " + name);
    }

    // 无参数
    public static String getVersion() {
        return "v1.0";
    }

    public static void main(String[] args) {
        int sum = add(3, 5);        // 调用并接收返回值
        System.out.println(sum);    // 8

        greet("小明");              // 调用 void 方法,不接返回值

        System.out.println(getVersion());   // v1.0
    }
}

方法签名的几个组成:

2. Java 是"值传递"!理解参数传递

这是新手最容易迷糊的概念。Java 只有值传递——但"值"对基本类型和引用类型含义不同:

public class PassByValue {

    // 1. 基本类型:传值的副本,方法内改不影响外部
    public static void doubleIt(int x) {
        x = x * 2;
        System.out.println("方法内 x = " + x);
    }

    // 2. 引用类型:传地址的副本,通过它可以改对象内部
    public static void addOne(int[] arr) {
        arr[0] = arr[0] + 1;
    }

    public static void main(String[] args) {
        int n = 10;
        doubleIt(n);
        System.out.println("方法外 n = " + n);    // 10(不变)

        int[] data = {1, 2, 3};
        addOne(data);
        System.out.println(data[0]);    // 2(被改了!)
    }
}

3. 方法重载(Overload)

同一个类中可以定义同名参数列表不同的多个方法,叫"重载"。编译器根据你传的参数类型/个数,自动决定调用哪个版本。

public class OverloadDemo {

    // 方法重载(Overload):同名、参数列表不同(个数/类型/顺序)
    // 返回类型不同不算重载,会编译报错

    public static int max(int a, int b) {
        return a > b ? a : b;
    }

    public static double max(double a, double b) {
        return a > b ? a : b;
    }

    public static int max(int a, int b, int c) {
        return max(max(a, b), c);
    }

    public static void main(String[] args) {
        System.out.println(max(3, 5));         // 5    调用 int 版
        System.out.println(max(3.5, 2.7));     // 3.5  调用 double 版
        System.out.println(max(3, 9, 5));      // 9    调用三参数版
    }
}

重载的好处:同一概念用同一名字,API 更简洁——如 System.out.println(int) / println(String) / println(double) 都是重载。注意:返回类型不同不算重载,参数列表必须不同。

4. 可变参数(int...)

有时候你想让方法接收任意多个参数(如 sum(1,2,3)sum(1,2,3,4,5)),用可变参数(varargs):

public class VarArgsDemo {

    // 可变参数:类型... 参数名,本质是数组
    // 调用时可以传 0~N 个参数,也可以直接传数组
    public static int sum(int... nums) {
        int total = 0;
        for (int n : nums) {
            total += n;
        }
        return total;
    }

    // 可变参数必须放参数列表最后,且一个方法只能有一个可变参数
    public static String join(String sep, String... parts) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < parts.length; i++) {
            if (i > 0) sb.append(sep);
            sb.append(parts[i]);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(sum(1, 2, 3));          // 6
        System.out.println(sum(1, 2, 3, 4, 5));    // 15
        System.out.println(sum());                  // 0(空参也行)

        int[] arr = {10, 20, 30};
        System.out.println(sum(arr));              // 60(直接传数组)

        System.out.println(join(", ", "a", "b", "c"));   // a, b, c
    }
}

可变参数的本质是数组——int... nums 在方法内就是 int[]。规则:

5. 递归(方法调用自己)

递归是"方法调用自己"的技巧,适合分治问题(阶乘、斐波那契、树/图遍历、回溯)。两个关键:

public class RecursionDemo {

    // 递归:方法调用自己,必须有"终止条件",否则栈溢出
    public static int factorial(int n) {
        if (n <= 1) return 1;        // 终止条件(递归出口)
        return n * factorial(n - 1); // 递归调用
    }

    // 经典:斐波那契数列 F(n) = F(n-1) + F(n-2)
    public static int fib(int n) {
        if (n < 2) return n;
        return fib(n - 1) + fib(n - 2);
    }

    public static void main(String[] args) {
        System.out.println(factorial(5));    // 120 (5! = 5*4*3*2*1)
        System.out.println(fib(10));         // 55

        // ⚠️ 递归太深会 StackOverflowError
        // factorial(100000);    // ❌ 栈溢出
    }
}

递归虽优雅但有性能开销:每次调用都要压栈,深度过大会栈溢出。fib(40) 这种朴素递归会重复计算,效率极低——实际工程中常用循环记忆化替代。

6. 静态方法(static)

static 修饰的方法属于类本身,不需要创建对象就能直接调用:类名.方法名()。Math 类的所有方法都是静态的。

public class StaticMethod {

    // 静态方法(类方法):用 static 修饰,属于类,直接用 类名.方法() 调用
    public static double circleArea(double r) {
        return Math.PI * r * r;
    }

    public static void main(String[] args) {
        // 调用静态方法:可以 类名.方法(),同类中可以省略类名
        double area = StaticMethod.circleArea(2.0);
        System.out.println(area);    // 12.566...

        // Math 类全是静态方法,这是经典例子
        System.out.println(Math.max(3, 5));        // 5
        System.out.println(Math.abs(-10));         // 10
        System.out.println(Math.sqrt(16));         // 4.0
    }
}

静态方法 vs 实例方法:

7. 方法的最佳实践

小结

这一章你掌握了 Java 方法的全部要点:定义、调用、值传递、重载、可变参数、递归、静态方法。下一篇我们看 Java 数组——存一组同类型数据的容器,是后面学集合的基础。

← 上一篇 Java 流程控制

下一篇 Java 数组

✈️💬