
java中字段不具有多态性,而方法具有运行时多态性:向上转型后访问字段取的是声明类型(父类)的成员变量值,而调用方法则执行实际类型(子类)的重写版本。
java中字段不具有多态性,而方法具有运行时多态性:向上转型后访问字段取的是声明类型(父类)的成员变量值,而调用方法则执行实际类型(子类)的重写版本。
在Java面向对象编程中,理解“向上转型(upcasting)”下的字段与方法行为差异,是掌握多态本质的关键。正如示例代码所示:
A x = new B(); // 向上转型:父类引用指向子类对象 System.out.println(x.i); // 输出 10 → 访问的是 A 类的字段 i System.out.println(x.shout()); // 输出 20 → 调用的是 B 类重写的 shout() 方法
其根本原因在于:字段(field)是静态绑定的,而实例方法(instance method)是动态绑定的。
- ✅ 方法重写(Override):
shout()在B中重写了A中的同名方法。JVM 在运行时根据对象的实际类型(B)决定调用哪个版本,这正是运行时多态的体现。 - ❌ 字段隐藏(Shadowing):
B中声明的int i = 20并未重写A的i,而是隐藏(shadow)了它。此时内存中同时存在两个独立的i字段:A.i(值为10)和B.i(值为20)。当通过A类型引用x访问i时,编译器依据引用的声明类型(A) 解析字段,因此读取的是A.i。
⚠️ 注意事项:
- 字段永远不参与多态,无论是否
public、protected或包级可见; - 若需实现类似“字段多态”的语义,应将字段设为
private,并通过protected或public的 getter/setter 方法封装访问逻辑(如getI()),再在子类中重写该方法; - 显式区分父子类同名字段可使用
this.i(当前类字段)或super.i(直接父类字段); - 编译器会在编译期完成字段解析(静态绑定),而方法调用在字节码中使用
invokevirtual指令,由 JVM 在运行时查虚方法表(vtable)确定具体实现。
总结:Java 的多态仅适用于非静态、非私有、非final的实例方法;字段、静态方法、final 方法、构造器均不支持运行时动态分派。设计类时,应避免公开字段,优先采用封装+重写getter的方式,以确保行为可预测、可继承、可维护。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











