Java方法重载在编译期通过静态分派确定调用版本,依据是参数的声明类型而非运行时实际类型;匹配优先级为:精确匹配→装箱拆箱→基本类型提升→可变参数。

Java 中的重载方法调用,不是运行时决定的,而是在编译阶段就锁定了具体调用哪一个版本。这个过程叫静态分派,核心依据只有一个:参数的编译期类型(也叫静态类型),而不是对象在运行时实际是什么类型。
静态分派只看“声明类型”,不看“真实对象”
比如你写:
Object obj = new String("hello");print(obj);
即使 obj 实际指向的是 String 实例,编译器也只认它声明为 Object 类型,所以会去匹配 print(Object),而不是 print(String)。哪怕你把 obj 设为 null,只要声明类型有对应方法,编译照样通过——因为根本没到运行时。
重载匹配按固定优先级顺序尝试
编译器对实参类型做匹配时,遵循明确的层级规则:
立即学习“Java免费学习笔记(深入)”;
- 先找完全一致的类型(精确匹配)
- 再考虑自动装箱/拆箱(如 int ↔ Integer)
- 接着是基本类型提升(如 byte → short → int → long → float → double)
- 最后才考虑可变参数(
void method(String...))
这意味着 method(10) 会优先调用 method(int),而不是 method(long) 或 method(Integer),除非前者不存在。
泛型擦除会让重载“撞车”
Java 编译后泛型信息被擦除,所以:
-
foo(List<String>)和foo(List<Integer>)在字节码里都变成foo(List) - 编译器直接报错:方法已定义,无法重载
这不是匹配失败,而是语法层面就不允许共存。解决办法是改名,或加一个类型不同的哑参数(比如 foo(List<String>, Void) 和 foo(List<Integer>, Class))。
重载和重写别混淆
子类加个参数不同的同名方法,不是重写父类方法,而是新增一个重载方法:
- 父类有
process(Object) - 子类加了
process(String) - 那么
child.process(new Object())走父类,child.process("abc")才走子类
判断是否重写,只看方法名、参数列表、返回类型(协变除外)是否完全一致;重载只要求方法名相同、参数列表不同。


















