Skip to content

方法重载

方法重载(Overload)让同一个方法名在不同参数下做不同的事。名字相同,参数不同,编译器会根据调用时传入的参数自动选择正确版本。

为什么需要重载

试想没有重载的世界:

java
// ❌ 必须给每个方法起不同的名字
int addInt(int a, int b) { return a + b; }
double addDouble(double a, double b) { return a + b; }
String addString(String a, String b) { return a + b; }

有了重载,简洁多了:

java
// ✅ 同一个名字,参数列表不同
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
String add(String a, String b) { return a + b; }

重载让 API 更简洁。调用者不需要记一堆方法名,记住一个就够了。

重载的判断规则

重载只关心一件事:参数列表必须不同

java
public class OverloadRules {

    // 这四个方法都构成重载
    void process(int a) { }                    // 参数个数不同
    void process(int a, int b) { }           // 参数个数不同
    void process(double a) { }                // 参数类型不同
    void process(int a, double b) { }         // 参数顺序不同
    void process(double a, int b) { }         // 参数顺序不同
}

下面这些不会构成重载:

java
public class NotOverload {

    // ❌ 只有返回值不同,不算重载
    int method() { return 0; }
    // String method() { return ""; }  // 编译错误

    // ❌ 只有参数名不同,不算重载
    void process(int a) { }
    // void process(int b) { }  // 编译错误

    // ❌ 只有 static 修饰符不同,不算重载
    static void process(int a) { }
    // void process(int a) { }  // 编译错误
}

与重写的对比

对比项重写 (Override)重载 (Overload)
发生位置父子类之间同一个类中
方法名必须相同必须相同
参数列表必须相同必须不同
返回类型必须相同或其子类可以相同或不同
访问修饰符不能缩小无关
关系同一个方法的不同实现完全不同的方法
java
class Parent {
    void display(int x) {
        System.out.println("Parent: " + x);
    }
}

class Child extends Parent {
    // 这是重写:参数列表相同
    @Override
    void display(int x) {
        System.out.println("Child: " + x);
    }

    // 这是重载:参数列表不同
    void display(String s) {
        System.out.println("Child: " + s);
    }
}

public class OverloadVsOverride {
    public static void main(String[] args) {
        Child obj = new Child();
        obj.display(10);          // 重写版本
        obj.display("hello");     // 重载版本
    }
}

构造方法重载

重载最常见的应用场景就是构造方法:

java
public class User {
    private String name;
    private int age;
    private String email;

    // 无参构造
    public User() {
        this.name = "匿名";
    }

    // 单参构造
    public User(String name) {
        this.name = name;
    }

    // 双参构造
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 全参构造
    public User(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
}

调用时,编译器根据参数自动选择:

java
new User();                          // 无参构造
new User("张三");                    // 单参构造
new User("李四", 25);               // 双参构造
new User("王五", 30, "a@b.com");   // 全参构造

细节:类型自动转换

当没有精确匹配的方法时,编译器会尝试自动类型转换:

java
public class TypePromotion {

    void process(int a) {
        System.out.println("int: " + a);
    }

    void process(double a) {
        System.out.println("double: " + a);
    }

    public static void main(String[] args) {
        TypePromotion obj = new TypePromotion();

        obj.process(10);       // 精确匹配 int 版本
        obj.process(10.5);      // 精确匹配 double 版本
        obj.process('A');       // char → int,自动提升
        obj.process((short) 5); // short → int,自动提升
    }
}

匹配优先级:精确匹配 > 自动类型提升 > 自动装箱 > varargs

java
public class PriorityDemo {

    void process(int i) {
        System.out.println("int");
    }

    void process(Integer i) {
        System.out.println("Integer");
    }

    void process(Object o) {
        System.out.println("Object");
    }

    void process(int... arr) {
        System.out.println("varargs");
    }

    public static void main(String[] args) {
        PriorityDemo obj = new PriorityDemo();
        Integer num = 10;

        obj.process(10);        // int(精确匹配)
        obj.process(num);       // Integer(精确匹配)
        obj.process("hello");   // Object
        obj.process(1, 2, 3);  // varargs
    }
}

常见错误

1. 与重写混淆

java
class Parent {
    void display(int a) {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    void display(int a, int b) {  // 这不是重写,是重载!
        System.out.println("Child");
    }
}

2. 误以为返回类型影响重载

java
class Example {
    int getValue() { return 1; }
    // double getValue() { return 1.0; }  // ❌ 编译错误:只有返回类型不同
}

实际应用

Java 标准库中到处是重载的影子:

java
// String 类
"hello".indexOf(99);      // 从指定位置开始查找
"hello".indexOf('e');     // 查找字符
"hello".indexOf("ell");   // 查找子串
"hello".indexOf("e", 1);  // 从指定位置开始查找子串

// System.out
System.out.println();         // 换行
System.out.println(true);     // 打印布尔
System.out.println(100);      // 打印整数
System.out.println("hello");  // 打印字符串
System.out.println('A');      // 打印字符

总结

方法重载让同一个名字承载多种功能,关键规则只有一条:参数列表必须不同

记住这张选择图:

调用 method(x)

有没有 method(精确类型)? → 有 → 调用
       ↓ 无
有没有 method(自动提升类型)? → 有 → 调用  (int → long → double → Object)
       ↓ 无
有没有 method(自动装箱类型)? → 有 → 调用  (int → Integer)
       ↓ 无
有没有 method(可变参数)? → 有 → 调用
       ↓ 无
编译错误

基于 VitePress 构建