重载要求方法名相同且参数列表不同,返回类型、修饰符、异常声明不参与区分;泛型擦除和可变参数需特别注意歧义与冲突。

方法名必须相同
重载的核心前提是多个方法共享同一个名称。如果方法名不同,哪怕参数、返回值完全一致,也属于普通方法,不构成重载。toString() 和 toStringBuffer() 就是两个独立方法,和重载无关。
参数列表必须不同
这是重载最关键的判断依据。JVM 仅根据方法名 + 参数类型(及顺序)来区分重载方法,**返回类型、修饰符、异常声明都不参与区分**。
- 允许的差异包括:
int与double、String与Object、int与Integer(自动装箱不影响重载判定)、参数个数不同、参数顺序不同(如foo(int, String)和foo(String, int)) - 不允许的“伪差异”:
int[]和int...—— 编译器会报错,因为它们在字节码层面被视为同一签名;ArrayList和ArrayList—— 泛型擦除后都是ArrayList,无法重载 - 注意隐式转换:定义了
void print(String s)和void print(Object o),调用print(null)会编译失败,因为编译器无法确定选择哪个——这是典型的歧义场景
不能只靠返回类型或 throws 子句区分
以下写法是非法的,编译直接报错:
public int getValue() { return 42; }
public String getValue() { return "42"; } // ❌ 编译错误:duplicate method
同理,仅改变 throws 声明也不行:
立即学习“Java免费学习笔记(深入)”;
public void read() throws IOException {}
public void read() throws SQLException {} // ❌ 编译错误
这是因为 JVM 方法签名(method descriptor)只包含名称和参数类型,不包含返回类型或异常类型。
访问修饰符和 static 不影响重载判定
public、protected、private、static、final 等修饰符可以任意组合,只要参数列表不同,就仍是合法重载。例如:
public void handle(String s) {}
private void handle(int i) {}
static void handle(double d) {}
但要注意:这些修饰符会影响调用可见性或绑定时机(比如 static 方法不参与多态),和重载本身无关。容易混淆的是重载和重写的区别——重写要求方法签名(含返回类型)完全一致且非 static,而重载只看参数列表。
最常被忽略的一点:泛型方法重载时,类型擦除后的签名冲突会导致编译失败,不是运行时行为;另外,可变参数 ... 在重载解析中优先级最低,有更精确匹配时不会触发它。










