java中属性和静态方法不具多态性,根本原因是它们采用编译期静态绑定:属性访问和静态方法调用均依据引用声明类型(左边类型)确定,而非对象实际类型;只有非static、非private、非final的实例方法才通过运行时动态绑定支持多态。

Java 多态机制中,属性(成员变量)和静态方法不具备多态性,根本原因在于它们的绑定方式不同:**方法调用走动态绑定(运行时决定),而属性访问和静态方法调用走静态绑定(编译时就确定)**。
属性不具有多态性:编译期就锁定引用类型中的字段
属性访问遵循“编译看左边,运行也看左边”原则。无论实际对象是哪个子类,只要引用声明为父类类型,访问的就是父类中定义的同名字段。
- 子类中声明同名字段,不是重写(override),而是隐藏(hiding)父类字段;两者在内存中独立存在。
- JVM 在编译阶段就根据引用的声明类型(即“左边”类型)确定访问哪个字段,不查实际对象类型。
- 例如:
Parent p = new Child(); System.out.println(p.value);输出的是Parent.value,哪怕Child自己也有value = 20。
静态方法不具有多态性:调用取决于引用类型,而非对象实际类型
静态方法属于类,不属于实例,因此它不参与继承链上的动态分派。调用哪个版本的静态方法,完全由引用变量的声明类型(编译时类型)决定。
- 子类中定义同名静态方法,也是隐藏(not override),不会触发多态行为。
- 即使写成
A a = new B(); a.staticMethod();,JVM 仍会调用A.staticMethod(),因为静态方法绑定发生在编译期。 - 这也意味着,静态方法无法被多态地“重写”,即便签名相同,也不会覆盖父类行为。
为什么只有非 static、非 private、非 final 的实例方法才有多态
这类方法满足 JVM 动态绑定的前提:它们会被纳入类的虚方法表(vtable),在运行时通过对象的实际类型查找并调用对应实现。
- private 方法:不可继承,自然无法被重写,编译器直接内联或绑定到当前类。
- final 方法:明确禁止重写,JVM 可优化为静态绑定。
- static 方法:绑定到类而非对象,与实例无关,无“运行时类型”可言。
- 构造方法:不参与继承体系,只用于创建对象,不被多态机制管理。
一个关键对比:方法里访问 this.field 为何能拿到子类值
这常让人困惑——既然属性没多态,为什么在重写方法里打印 this.value 却是子类的值?
- 因为
this是运行时对象本身,this.value的访问发生在方法体内部,此时已进入子类方法上下文。 - 而
引用.字段这种直接访问,是编译器按引用类型解析的,和this的语义不同。 - 换句话说:字段无多态,但
this指向的是真实对象,其内部字段自然属于该对象所属类。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











