静态方法无法被重写,因其绑定发生在编译期、依赖声明类型而非运行时类型,不参与虚方法表机制;子类同名静态方法仅为“隐藏”,无多态性。

静态方法无法被重写,根本原因在于运行时多态依赖的是对象的实际类型(运行时类型)和虚方法调用机制,而静态方法绑定发生在编译期,与对象实例无关。
运行时多态的核心:动态绑定基于对象实例
运行时多态要求方法调用在程序运行时,根据引用所指向对象的真实类型,查找并执行对应类中被重写的实例方法。这依赖于 JVM(或类似运行环境)为每个类维护的虚方法表(vtable),表中存放的是可被重写、支持动态分派的非静态、非私有、非 final 的实例方法。
关键点:
- 调用目标由对象实际类型决定(如
Animal a = new Dog(); a.speak();调用Dog.speak()) - 该机制只对实例方法生效;静态方法不参与虚方法表构建
- 静态方法属于类本身,调用时只看引用的声明类型(即编译时类型)
静态方法调用是编译期静态绑定
当写 a.staticMethod()(其中 a 是父类引用),编译器直接根据 a 的声明类型(如 Animal)确定调用哪个类的静态方法,不查对象实际类型,也不走 vtable。即使子类定义了同签名静态方法,也仅视为“独立存在”的另一个方法,而非对父类方法的覆盖。
例如:
-
Animal.show();→ 调用Animal.show() -
Dog.show();→ 调用Dog.show() -
Animal a = new Dog(); a.show();→ 仍调用Animal.show()(不是Dog的)
“隐藏”(Hiding)的本质是名称屏蔽,而非重写
子类定义同名静态方法,不会改变父类方法的行为,只是让该名称在子类作用域中指向自己的实现。这种关系叫“隐藏”,特点是:
- 无多态性:无法通过父类引用触发子类版本
- 不破坏父类静态方法:父类方法依然可通过
Animal.show()显式访问 - 编译器按引用类型选择方法,不是按对象类型
一个直观对比
假设 Animal 和 Dog 都有 speak()(实例方法)和 info()(静态方法):
-
Animal a = new Dog(); a.speak();→ 输出 “Woof!”(运行时多态生效) -
Animal a = new Dog(); a.info();→ 输出 “I'm an Animal”(静态绑定,看a声明为Animal) -
Dog d = new Dog(); d.info();→ 输出 “I'm a Dog”(此时声明类型是Dog,所以调用Dog.info())

















