Java重载方法的静态分派由编译器在编译期完成,仅依据参数的静态类型(声明类型)和方法签名匹配,不依赖运行时对象实际类型;例如Object obj = new String("hi")调用print(obj)时,编译器只认obj为Object类型,故绑定print(Object),而非print(String)。

Java 重载方法的静态分派完全由编译器在编译期完成,不依赖运行时对象的实际类型,只看参数的静态类型(即声明类型)和方法签名的匹配程度。
静态分派依据的是参数的编译期类型
编译器检查调用点上每个实参的静态类型(比如变量声明类型、字面量类型、表达式的编译时推导类型),然后在当前类及其父类的符号表中查找所有同名方法,筛选出参数个数、类型、顺序完全匹配的候选方法。
- 例如:
Object obj = new String("hi"); print(obj);—— 编译器只看到obj是Object类型,就选print(Object),哪怕它实际指向String实例 - 再如:
print("abc")中"abc"是字面量,静态类型为String,直接绑定到print(String) -
Integer i = 5; print(i);中i静态类型是Integer,若同时存在print(int)和print(Integer),则优先选print(Integer)(不触发自动拆箱)
静态分派不考虑返回值、异常或修饰符
方法是否构成重载,只由方法名 + 参数列表(类型、数量、顺序)决定。以下改动不会产生新重载:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 仅改变返回值类型 → 编译报错:
method() is already defined - 仅增删
throws声明 → 不影响重载判断,编译不通过 - 访问修饰符不同(
public/private)→ 也不参与区分
静态分派发生在编译阶段,与JVM无关
这个过程由 javac 完成,生成的字节码里已经明确写死调用哪个方法(如 invokevirtual PrintStream.println:(Ljava/lang/String;)V)。JVM 运行时不再重新选择,也不查虚方法表。
立即学习“Java免费学习笔记(深入)”;
- 没有运行时多态行为:即使子类定义了更具体的重载版本,只要引用类型没变,就进不了那个方法
- 泛型擦除后可能引发歧义:比如
handle(List<String>)和handle(List<Integer>)擦除后都是handle(List),编译直接报错 - 自动装箱有固定优先级:
handle(int)和handle(Integer)共存时,handle(5)一定走int版本;只有传入Integer类型变量才会选包装类版本
静态分派和动态分派协同工作:先定形,再定实
当一个调用同时涉及重载和重写(比如 animal.speak() 中 animal 是重载方法的参数,而 speak() 本身被重写),编译器先根据参数静态类型完成重载选择(静态分派),之后 JVM 再根据接收者实际类型执行重写方法(动态分派)。
- 典型例子:
void feed(Animal a)和void feed(Dog d)是重载;Dog类重写了Animal.speak()。调用feed(new Dog())时,编译器按Dog静态类型选feed(Dog);进入方法后,a.speak()才由 JVM 查虚方法表,调用Dog.speak() - 也就是说:重载决定“调哪个方法”,重写决定“这个方法具体执行谁的实现”

















