静态方法不能被重写,只能被隐藏;jvm在编译期根据引用类型静态绑定,与实际对象类型无关,故parent p = new child(); p.staticmethod()调用parent的版本。

静态方法不能被重写,只能被隐藏
Java里static方法不参与多态,子类中定义同签名的static方法时,不是覆盖(override),而是隐藏(hide)。JVM在编译期就绑定调用哪个类的静态方法,和变量类型有关,和实际对象类型无关。
常见错误现象:Parent p = new Child(); p.staticMethod(); 调用的是Parent.staticMethod(),不是Child里的——很多人以为这是“重写失败”,其实是根本没走重写逻辑。
- 静态方法调用由**引用类型**决定,不是运行时对象类型
- 子类方法必须用
static修饰,否则编译报错:static method cannot hide instance method - 哪怕子类方法去掉
static,也不会变成重写,而是编译错误
实例方法重写 vs 静态方法隐藏的调用差异
区别核心在「绑定时机」:实例方法是动态绑定(运行时看new的是谁),静态方法是静态绑定(编译时看左边声明类型是谁)。
示例:
立即学习“Java免费学习笔记(深入)”;
class A { static void f() { System.out.println("A.f"); } }
class B extends A { static void f() { System.out.println("B.f"); } }
A a = new B();
a.f(); // 输出 "A.f" —— 看a的声明类型A
B b = new B();
b.f(); // 输出 "B.f"
- 即使
a实际指向B实例,a.f()仍调用A.f() - 如果把
f()改成非static,输出立刻变成"B.f" - IDE通常不会给静态隐藏加“override”提示,但会警告“method hides a static method in superclass”
@Override注解对静态方法无效
给子类静态方法加@Override会直接编译失败:method does not override or implement a method from a supertype。这其实是编译器在帮你确认:你写的不是重写。
- 加了
@Override还编译通过?说明父类对应方法也是static,且签名一致 → 这是隐藏,不是重写 - 想强制检查是否真有继承关系?删掉
@Override再试;或者把父类方法改成final,子类隐藏会继续成功(因为隐藏不受final限制) - 误加
@Override是新人高频错误,尤其从实例方法复制粘贴过来改static时
什么时候该用静态方法隐藏?谨慎使用
极少有正当理由需要刻意隐藏静态方法。多数情况是设计信号:这个逻辑本不该是静态的,或本该抽成工具类独立存在。
- 常见误用场景:想“重写工厂方法”,结果写了
static create()隐藏 → 改用抽象方法+实例工厂更清晰 - 若真要按类型返回不同实例,应使用非静态的
create()或依赖注入 - 唯一较合理的情况:工具类层级扩展,如
StringUtils子类提供额外static工具,但需明确命名区分(如AdvancedStringUtils),避免靠隐藏来“多态”
隐藏容易,但调用行为反直觉;一旦涉及继承链和多态预期,静态方法就是个隐形陷阱。








