java方法重载是编译期静态绑定,依据形参类型匹配签名;重写是运行期动态绑定,依据实际对象类型;参数传递均为值传递,引用类型传递的是地址副本。

Java 中的方法定义和调用本身不难,但重载(overload)和重写(override)经常被混淆,参数传递机制又常被误认为“支持引用传递”,这些地方一旦理解偏差,会在调试时浪费大量时间。
方法定义与调用:签名决定能否被找到
方法是否能被调用,只取决于编译期能否匹配到一个明确的 方法签名(即方法名 + 参数类型序列,与返回值、修饰符无关)。JVM 不关心返回值类型,所以仅靠返回值不同无法构成重载。
-
public void print(String s)和private void print(String s)是同一个签名,编译失败(重复声明) -
void print(int x)和void print(Integer x)是两个不同签名,可以共存(自动装箱不改变签名判定时机) - 调用
print(5)会优先匹配int版本,而非Integer;除非显式写成print((Integer)5)
重载(Overload):编译期绑定,看的是“形参类型”
重载发生在同一个类中,是静态多态。编译器根据调用处传入的实参类型(不是运行时对象类型!)决定调用哪个方法。
- 子类中定义
void show(Object o)和void show(String s),调用show(null)会编译报错:歧义(null可匹配任意引用类型) -
float类型实参传给double形参方法是合法的(自动提升),但不会触发float版本重载(如果存在) - 可变参数(
...)是重载的“兜底选项”,只有在无更精确匹配时才启用;method(String...)比method(Object)更具体
重写(Override):运行期绑定,看的是“实际对象类型”
重写要求子类方法与父类方法具有相同签名(包括返回类型协变)、访问权限不能更严格、不能抛出新或更宽泛的检查异常。它由 JVM 在运行时通过虚方法表(vtable)动态分派。
立即学习“Java免费学习笔记(深入)”;
- 若父类方法是
protected void run(),子类重写为public void run()合法;但private void run()是定义新方法,不是重写 -
@Override注解不是必需的,但强烈建议加上——它能在父类方法被删/改名时立刻报错,而不是静默变成重载或新方法 - 构造器、
static方法、final方法不能被重写;其中static方法看似“重写”,实则是隐藏(hiding),调用取决于引用类型而非对象类型
参数传递:Java 只有值传递,对象也是传“引用的值”
Java 中所有参数都是值传递。基本类型传的是值的副本;引用类型传的是“对象地址的副本”。这意味着你无法在方法内让外部引用指向新对象,但可以通过该引用来修改对象状态。
-
void swap(StringBuilder a, StringBuilder b) { StringBuilder t = a; a = b; b = t; }—— 外部变量不会交换,因为a和b是局部拷贝 -
void append(StringBuilder sb) { sb.append("x"); }—— 外部sb内容会变,因为操作的是同一堆内存中的对象 - 不可变类(如
String)会让这个机制显得像“传值”,其实是对象本身不允许修改,不是传递方式变了
最容易被忽略的是:重载解析完全在编译期完成,而重写调用在运行期才确定;参数传递机制则从头到尾没有“引用传递”这回事——哪怕你看到 list.add() 改变了外部列表,也只是因为你持有的是同一份堆内存的地址副本。










