V
Vel·ToolKit
简洁 · 高效 · 即开即用
ZH
第 5 章 / 共 20 章

方法

签名、重载、可变参数、static、方法引用

方法定义

格式:[修饰符] 返回类型 方法名(参数列表) { 方法体 }。返回类型 void 表示不返回值。

// Methods.java
public class Methods {
    // static 方法可以直接通过类名调用
    static int add(int a, int b) {
        return a + b;
    }

    static void greet(String name) {
        System.out.println("Hello, " + name);
    }

    public static void main(String[] args) {
        System.out.println(add(2, 3));
        greet("Alice");
    }
}

重载(Overloading)

同一类里方法名相同但参数列表不同(个数 / 类型 / 顺序),编译器按调用处的参数类型选最匹配的版本。返回类型不参与重载判断。

// Overload.java
public class Overload {
    static int sum(int a, int b) { return a + b; }
    static double sum(double a, double b) { return a + b; }
    static int sum(int a, int b, int c) { return a + b + c; }

    public static void main(String[] args) {
        System.out.println(sum(1, 2));         // 调用第一个
        System.out.println(sum(1.5, 2.5));     // 调用第二个
        System.out.println(sum(1, 2, 3));      // 调用第三个
    }
}

可变参数 String...

T... 等价于内部是 T[] 数组,调用时可以传任意个该类型实参。可变参数必须是参数列表的最后一个。

// Varargs.java
public class Varargs {
    static int max(int... nums) {
        if (nums.length == 0) {
            throw new IllegalArgumentException("need at least one");
        }
        int m = nums[0];
        for (int n : nums) {
            if (n > m) m = n;
        }
        return m;
    }

    public static void main(String[] args) {
        System.out.println(max(3, 1, 4, 1, 5, 9, 2, 6));  // 9

        // 也可以直接传数组
        int[] arr = {7, 2, 8};
        System.out.println(max(arr));                      // 8
    }
}

static 方法 vs 实例方法

static 方法属于类,通过 类名.方法名 调用,不能访问实例字段;实例方法属于对象,必须先有 new XX()。第 6 章会展开类与对象,这里先看用法对比。

// StaticVsInstance.java
public class StaticVsInstance {
    private String name;

    public StaticVsInstance(String name) {
        this.name = name;
    }

    void hello() {  // 实例方法
        System.out.println("hi, " + name);
    }

    static String capitalize(String s) {  // static 方法
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    public static void main(String[] args) {
        // static 直接调
        System.out.println(capitalize("alice"));   // Alice

        // 实例方法必须先 new
        StaticVsInstance obj = new StaticVsInstance("Bob");
        obj.hello();
    }
}

参数传值机制

Java 永远是"按值传递"。但对引用类型,传过去的是引用的副本——函数内通过引用能修改对象内部,但重新赋值 obj = new ... 不会影响外面。

// PassByValue.java
import java.util.ArrayList;
import java.util.List;

public class PassByValue {
    static void changeInt(int n) {
        n = 99;  // 改的是本地副本
    }

    static void mutateList(List<Integer> list) {
        list.add(99);  // 通过引用改了对象内部
    }

    static void reassignList(List<Integer> list) {
        list = new ArrayList<>();  // 改的是本地引用,不影响外面
        list.add(-1);
    }

    public static void main(String[] args) {
        int n = 1;
        changeInt(n);
        System.out.println(n);             // 1

        List<Integer> nums = new ArrayList<>(List.of(1, 2, 3));
        mutateList(nums);
        System.out.println(nums);          // [1, 2, 3, 99]
        reassignList(nums);
        System.out.println(nums);          // [1, 2, 3, 99] 没变
    }
}

方法引用 Class::method

Java 8 起方法可以作为"值"传递。Class::staticMethod、obj::instanceMethod、Class::instanceMethod、Class::new 四种形式。第 14 章 Lambda 会更深入。

// MethodRef.java
import java.util.List;

public class MethodRef {
    public static void main(String[] args) {
        List<String> names = List.of("Alice", "Bob", "Carol");

        // 方法引用:System.out::println 等价于 s -> System.out.println(s)
        names.forEach(System.out::println);

        // 静态方法引用:Integer::parseInt 等价于 s -> Integer.parseInt(s)
        List<String> nums = List.of("1", "2", "3");
        int sum = nums.stream().mapToInt(Integer::parseInt).sum();
        System.out.println("sum=" + sum);
    }
}