Java中方法签名由方法名和参数列表(含类型、数量、顺序)构成,不包括返回类型、访问修饰符、异常声明等;它是编译期重载解析的唯一依据,决定静态绑定结果。

方法签名决定重载解析的全部依据,而重载解析本身就是静态绑定最典型的体现——它在编译期完成,完全不依赖运行时对象的实际类型,只看变量声明类型和传入参数的字面类型。
方法签名到底包含什么
Java中一个方法的签名 = 方法名 + 参数类型的**顺序、个数与具体类型**。注意:返回值、访问修饰符(public/private等)、异常声明、甚至是否static或final,统统不参与签名构成。
- print(String) 和 print(Object) 是两个不同签名
- print(int) 和 print(Integer) 也是两个不同签名(自动装箱发生在重载解析之后)
- void calc(double x) 和 int calc(double x) 签名相同 → 编译报错,不能共存
重载解析如何一步步选中方法
当你写下 a.method(5) 这行代码,编译器会按固定流程走:
- 先锁定变量 a 的**声明类型**(比如是 Parent 类),不是它实际指向的 Child 对象
- 在 Parent 类及其所有可访问父类(仅限 public 方法)中,收集所有名为 method 的方法
- 逐个比对每个方法的参数类型,寻找与字面量 5(即 int 类型)**最精确匹配**的那个签名
- 如果找到唯一匹配(如 method(int)),就绑定;如果模糊(如只有 method(long) 和 method(Float)),则按类型提升规则选;若仍不唯一,编译失败
实战中容易踩坑的典型场景
以下代码能清晰暴露“静态绑定只看声明类型+字面参数类型”的本质:
class A { void show(int x) { System.out.println("int"); } }
class B extends A { void show(long x) { System.out.println("long"); } }
A a = new B();
a.show(10); // 输出 "int" —— 编译器只在 A 中找,B 的 show(long) 不参与解析
- 即使 a 实际是 B 实例,但声明为 A,编译器根本不会查看 B 中新增的重载方法
- 把 a.show(10) 改成 a.show(10L),依然报错:因为 A 中没有 show(long),找不到匹配签名
- 若在 A 中加一个 show(Object o),那么 a.show(null) 就会调用它——null 可匹配任意引用类型,但优先选最具体的(无子类重载时就是 A 自己的)
为什么重载不能靠运行时类型区分
因为重载解析必须在编译期完成,而此时 JVM 还没启动,对象还没创建,更谈不上知道 new 出来的是哪个子类实例。所以:
- 重载是“同名不同参”的编译期契约,和多态无关
- 想让行为随实际对象变化?得用重写(override)+ 动态绑定,而不是重载
- 混用重载和重写极易造成误解:子类里写一个和父类重载签名相同但参数不同的方法,看起来像“覆盖”,其实只是新增了一个独立方法










