Java方法重载解析在编译期静态完成,优先匹配实参的编译时类型;按精确匹配→基本类型转换→装箱/可变参数三级优先级筛选,一旦某级有匹配即终止后续判断,返回类型和修饰符不参与解析。

Java 方法重载的“解析”不是运行时决定的,而是在编译阶段由编译器静态完成的。理解这个过程,关键在于抓住一点:编译器只看实参的编译时类型,不看运行时实际对象是什么;它按固定优先级从多个同名方法中选出最具体、最匹配的一个,而不是“差不多就行”的那个。
重载解析分三步走:精确 → 转换 → 装箱/可变
编译器对候选方法的筛选有明确顺序,一旦某一层找到至少一个匹配,就不再往下看:
-
精确匹配:实参类型与形参类型完全一致(如传
int,方法参数是int) -
基本类型自动转换:小范围转大范围,如
byte→int、int→long、float→double;但int→short不行(会丢失精度) -
装箱/拆箱 + 可变参数:先尝试自动装箱(
int→Integer)或拆箱(Integer→int),再考虑可变参数(void f(String...))。这两类匹配优先级最低,且互斥——如果装箱能匹配,就不会走可变参数。
为什么 null 常引发意外调用?
当方法重载涉及引用类型,又传入 null,编译器无法靠值判断,只能靠类型。例如:
void print(String s) { ... }
void print(Integer i) { ... }
print(null); // 编译错误:歧义!String 和 Integer 都是 null 的合法类型
但如果加上一个更具体的类型,比如:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
void print(String s) { ... }
void print(Object o) { ... }
print(null); // 成功,调用 print(String),因为 String 比 Object 更具体
编译器选的是最具体的可应用方法,不是随便挑一个。
可变参数是“兜底选项”,但容易被忽略
void log(String msg) 和 void log(String... msgs) 同时存在时:
-
log("hello")→ 调用第一个(精确匹配) -
log("a", "b")→ 只能调用第二个(可变参数唯一匹配) - 但
log((String) null)或log(new String[]{})就可能绕过直觉,触发可变参数版本
可变参数匹配只在前两层都找不到可行方法时才启用,但它一旦启用,就可能掩盖本该报错的场景(比如参数个数明显不对却没报错)。
返回类型和 static 修饰符完全不影响解析
编译器做重载解析时,压根不看:
- 方法返回值是
int还是String - 方法是不是
static - 访问修饰符是
public还是private
只要方法名相同、参数列表(类型+数量+顺序)相同,哪怕一个是 static、一个是实例方法,也直接编译失败——因为签名重复,不是重载,而是冲突。

















