静态方法不能被重写,只能被隐藏;因其绑定发生在编译期,依赖引用的声明类型而非对象的实际类型,不参与虚方法表和运行时多态机制。

静态方法不能被重写,只能被“隐藏”(Hiding);而实例方法才能被真正重写(Overriding)。这是 Java 多态机制中最容易混淆的一点,关键在于绑定时机和调用依据不同。
静态方法的隐藏(Hiding)是怎么发生的
当子类定义了一个与父类签名完全相同的静态方法(同名、同参数、同返回类型),它不会覆盖父类方法,而是将父类的静态方法“隐藏”起来。此时:
- 调用哪个版本,只看引用变量的声明类型,和实际对象类型无关
- 没有运行时多态,完全是编译期决定的
- 父类方法依然存在,可通过
父类名.方法名()显式调用
实例方法的重写(Overriding)才是真正的多态
当子类重写一个非 private、非 static 的实例方法时:
- 调用哪个版本,取决于运行时对象的实际类型
- 即使引用是父类类型,只要指向子类实例,就执行子类方法
- 这是动态绑定,支撑了面向对象的核心特性——多态
一段对比代码就能看清区别
假设父类 A 和子类 B extends A 都有 static void test() 和 void run():
A a = new B(); a.test(); // 输出 A.test() —— 静态方法:看左边 a 是 A 类型 a.run(); // 输出 B.run() —— 实例方法:看右边 new B(),真正重写生效
再换一种写法:B b = new B(); b.test(); 会输出 B.test(),因为声明类型是 B。可见,静态方法的调用不依赖对象,只依赖引用声明。
为什么 private 和 static 方法都不能重写
本质原因一致:它们都不参与运行时动态分派。
- private 方法对子类不可见,连继承都没有,自然谈不上重写
- static 方法属于类,不是对象行为,绑定发生在编译期,JVM 不会查虚方法表(vtable)
- 两者都可被子类“同名定义”,但这只是独立的新方法,和父类方法无覆盖关系

















