方法重载仅由名称和参数类型序列(含个数与顺序)决定,返回值、throws声明、访问修饰符、形参名及别名均不参与签名;泛型擦除后参数列表相同亦视为重复定义。

因为调用时可能根本没用到返回值,编译器无法凭空判断该选哪个方法。
调用语句本身不提供返回类型线索
写 doWork(); 这种语句时,括号里空空如也,编译器只看到方法名和参数个数为 0,完全不知道你“本意”是想要 int 还是 String。如果允许仅靠返回值区分重载,同一行代码就可能对应多个实现,编译器当场卡住——这不是功能缺失,而是主动拒绝歧义。
语言规范明确排除返回值参与签名
Java 和 C++ 都规定:方法/函数签名 = 名字 + 参数类型序列(含个数与顺序),返回值不在其中。这意味着:
- void print(String) 和 String print(String) 在字节码或符号表里被视为完全相同的签名,直接报错“重复定义”
- JVM 加载、链接阶段,以及 C++ 的 name mangling(符号修饰)都只编码参数类型,忽略返回值
- 泛型擦除后若只剩相同参数列表(如 handle(List) 写两次),同样被拒
看似不同但实际无效的改动
这些操作不会构成重载,反而导致编译失败:
- 只改返回类型(int get() ↔ String get())
- 只增删 throws 声明(read() ↔ read() throws IOException)
- 只调换访问修饰符(public run() ↔ private run())
- 只重命名形参(set(int a) ↔ set(int b))
- 用 typedef 或包装类别名替代(void f(int) ↔ void f(Id),Id 是 int 别名)
真正起作用的参数差异
只有参数列表产生可观测区别,才能触发重载解析:
- 数量不同:log(String) 和 log(String, int)
- 类型不同:add(int, int) 和 add(double, double)(注意基本类型优先于包装类)
- 顺序不同:build(String, int) 和 build(int, String)(合法但慎用,易降低可读性)
- 可变参数作为兜底:sum(int...) 只在没有更精确匹配(如 sum(int, int))时才被选中











