跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

在Java里重写和重载方法的区别_Java方法重载与重写说明

重写要求子类继承父类且方法名、参数列表、返回类型(或协变)一致,运行时动态绑定;重载发生在同一类中,仅需方法名相同、参数列表不同,编译期静态绑定。 重写(Override)必须满足的继承关系 重写只发生在子类继承父类(或实现接口)时,子类提供与父类
同名、同参数列表、同返回类型(或协变返回类型)
的方法。JVM 在运行时根据对象实际类型决定调用哪个版本,这是多态的基础。 常见错误现象:
private
方法无法被重写(子类里同名方法只是新定义)、
static
方法看似“重写”实为隐藏(编译期绑定,不具多态性)、返回类型不兼容(如父类返回
Object
,子类返回
String
是合法的,但返回
Integer
就不行)。 必须用
@Override
注解显式声明(强烈建议),否则 IDE 和编译器能帮你捕获拼写错误或签名不匹配 访问修饰符不能比父类更严格(
public
→
protected
合法,反之不行) 父类方法是
final
或
static
,子类无法重写 重载(Overload)发生在同一个类的作用域内 重载不要求继承关系,只要在同一个类(或同一个接口)中,方法名相同但
参数列表不同
(参数个数、类型、顺序任一不同即可),返回类型和访问修饰符可任意。编译器在编译期就根据调用处的实参类型和数量确定调用哪个方法。 容易踩的坑:
return
类型不同不算重载(编译报错:duplicate method);自动拆箱/装箱可能引发意外匹配(比如传
int
时,
method(int)
和
method(Integer)
都存在,优先选
int
版本);泛型擦除后若仅靠返回类型区分,也会编译失败。 立即学习 “ Java免费学习笔记(深入) ”; 参数类型差异要足够明确,避免因隐式转换导致调用歧义
varargs
(如
String...
)是重载的“兜底选项”,应放在重载组的最后声明 构造方法也能重载,且非常常见(如
new ArrayList()
vs
new ArrayList(Collection)
) 编译期绑定 vs 运行期绑定的关键区别 重载是静态绑定(编译期决定),重写是动态绑定(运行期决定)。这意味着: Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 如果变量声明类型是父类,但指向子类实例,调用重写方法会执行子类逻辑;而调用重载方法,只看**声明类型**和**实参字面量类型**,跟实际对象无关。
class A { void m(Object o) { System.out.println("A-Object"); } } class B extends A { void m(String s) { System.out.println("B-String"); } } A a = new B(); a.m("test"); // 输出 "A-Object" —— 因为 a 声明为 A,A 中没有 m(String),只能向上转型调用 m(Object)
这个例子说明:重载解析完全依赖引用类型(
A
)的可见方法签名,而不是实际对象(
B
)有哪些方法。 IDE 和编译器如何帮你识别混淆点 IntelliJ / Eclipse 对
@Override
有强校验:如果标注了但找不到可重写的方法,立刻报错;没标注但实际构成重写,会提示“Missing @Override”。而重载无此注解支持,全靠你手动核对参数列表。 鼠标悬停在方法调用上,IDE 显示“resolved to …” 可确认当前是重载还是重写路径 使用
javap -c
查看字节码:重写方法调用用的是
invokevirtual
,重载方法调用取决于编译期推断,可能是
invokestatic
或
invokevirtual
,但目标方法签名已固化 单元测试中改变父类引用的实际类型,是验证重写是否生效最直接的方式 最容易被忽略的是:子类中一个方法,既可能因为父类有同签名方法而构成重写,又可能因为本类已有相似签名方法而构成重载——这时候得同时满足两套规则,稍有不慎就会触发编译错误或行为偏离预期。

相关文章