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