java中static方法不能被重写只能被隐藏,因其实现静态绑定(看引用声明类型),而实例方法是动态绑定(看实际对象类型);字段同理只有隐藏无重写。

为什么子类里写了个同名方法,有时候调用的是父类的?
因为 Java 里 static 方法不能被重写(override),只能被隐藏(hiding)。这是最常让人困惑的根源:看起来一样,行为却完全不同。
关键区别在绑定时机——实例方法是运行时动态绑定(看实际对象类型),static 方法是编译时静态绑定(看引用变量声明类型)。
- 如果你用
Parent p = new Child();,再调p.staticMethod(),执行的是Parent.staticMethod() - 同样代码下,调
p.instanceMethod(),执行的是Child.instanceMethod() - 哪怕
Child里写了public static void instanceMethod()(加了static),它也不是重写,而是意外地把实例方法“遮住”了——编译都过不去
怎么一眼判断是 Override 还是 Hiding?
看方法签名是否满足重写条件,再看有没有 static。不满足重写条件 + 带 static → 隐藏;满足重写条件 + 不带 static → 重写。
重写的硬性要求:@Override 注解能通过、返回类型协变、访问权限不能更严格、异常不能新增检查型异常。
立即学习“Java免费学习笔记(深入)”;
-
static方法加@Override→ 编译错误:method does not override or implement a method from a supertype - 子类方法参数列表和父类不一致 → 不是重写,也不是隐藏,就是个新方法(overload)
- 父类方法是
private→ 子类同名方法一定是新方法,既不是重写也不是隐藏(private不参与继承)
重写和隐藏在多态调用中表现不同
多态只对实例方法生效。所谓“父类引用指向子类对象”,这个“多态性”对 static 方法完全无效。
class A { static void f() { System.out.println("A.f"); } }
class B extends A { static void f() { System.out.println("B.f"); } }
A x = new B();
x.f(); // 输出 "A.f" —— 看的是 x 的声明类型 A
换成实例方法:
class A { void f() { System.out.println("A.f"); } }
class B extends A { void f() { System.out.println("B.f"); } }
A x = new B();
x.f(); // 输出 "B.f" —— 看的是 new B() 的实际类型
- 别指望靠改引用类型来“切换”
static方法行为;它根本不响应运行时类型 - 如果真需要类似多态的静态行为,得手动用工厂、策略类或反射,而不是依赖方法名重复
容易被忽略的坑:字段也有隐藏,但没有重写
字段(成员变量)也存在隐藏,但 Java 根本不存在“字段重写”。哪怕子类定义了同名 public int x,它和父类的 x 是两个独立变量。
访问哪个字段,取决于引用类型,不是实际对象类型——这点和 static 方法一致,但和实例方法相反。
-
((A)new B()).x访问的是A.x;((B)new B()).x访问的是B.x - 这导致用 getter/setter 封装字段很重要:只有方法能真正实现运行时多态,字段永远静态绑定
- IDE 提示“field hides another field”不是警告,是事实陈述——你确实藏了一个字段,而且很可能自己都没意识到
static 方法隐藏一样,不报错、不抛异常、也不触发多态,只是静默地按声明类型取值。这种“看似继承实则割裂”的行为,在调试时最容易漏掉。










