java中多态对成员变量和静态方法统一遵循“看左边”原则,即只依据引用变量的声明类型(编译时类型)确定访问目标:成员变量仅存在隐藏而非重写,jvm在编译期直接按声明类型定位字段;静态方法属于类而非实例,调用由声明类型决定,采用静态绑定,不参与运行时动态分派。

Java 中多态对成员变量和静态方法的处理,统一遵循“看左边”——也就是只依赖引用变量的**声明类型**(编译时类型),不关心 new 出来的实际对象是谁。这不是语法随意设计,而是由它们的本质决定的。
成员变量:没有重写,只有隐藏
子类中定义与父类同名的成员变量,不会覆盖父类变量,只是“隐藏”了它。JVM 在访问字段时,不查虚方法表(vtable),也不做运行时类型判断,而是直接根据引用类型在编译期就确定字段归属。
- 编译器看到 Animal a = new Dog();,就知道 a 是 Animal 类型,访问 a.name 就去 Animal 类里找 name 字段
- 即使 Dog 类也有自己的 name 字段,只要不是通过 Dog 类型的引用访问,就不会用到它
- 想访问 Dog 的 name?得显式转型:((Dog)a).name,或者直接用 Dog 类型声明
静态方法:属于类,不依赖实例
静态方法随类加载而存在,内存中只有一份,它不绑定任何对象,自然无法参与多态。调用哪个类的静态方法,完全由引用变量的声明类型决定,跟右边 new 的是什么毫无关系。
- Animal a = new Dog(); a.eat(); → 编译器查 Animal 类是否有静态 eat() 方法,有就绑定;Dog 类里的同名静态方法不会被触发
- 如果写成 Dog d = new Dog(); d.eat();,才调用 Dog.eat()
- 这叫静态绑定(早期绑定),发生在编译阶段,连对象都没创建,更谈不上运行时类型
为什么这样设计?安全 + 确定性
字段和静态方法不参与动态分派,是因为它们不具备“可重写性”。如果允许它们按运行时类型调用,会导致语义混乱和编译期不可预测:
- 字段访问若看右边,同一个引用在不同上下文可能读到不同内存位置,破坏封装和可读性
- 静态方法若支持“多态调用”,就违背了“静态即类级”的根本语义,也容易引发类初始化顺序问题
- 编译期就能明确字段和静态方法归属,让 IDE 提示、编译检查、代码分析都更可靠
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











