字段访问走静态绑定(编译时看声明类型),方法调用走动态绑定(运行时看实际类型);Java不支持字段多态,子类同名字段仅隐藏父类字段,而非重写。
这是初学者最常卡住的地方:明明 Animal a = new Dog();,a.speak() 调的是 Dog.speak(),可 a.name 却是父类定义的值,甚至子类重写了同名字段也无效。
根本原因在于——方法调用走动态绑定(运行时看实际类型),字段访问走静态绑定(编译时看声明类型)。Java 不支持字段多态。
name 改成 getName(),并在子类中重写它不能。比如 Animal a = new Dog();,即使 Dog 有 fetch() 方法,a.fetch() 编译直接报错:cannot resolve symbol fetch。
因为编译器只认 a 的声明类型(Animal),它不知道背后是不是 Dog。这和多态无关,是类型系统的基本规则。
((Dog) a).fetch()
instanceof 检查,否则可能抛 ClassCastException
在父类构造器中调用一个可被子类重写的方法(如 this.init()),而子类恰好重写了它,结果会出人意料:方法确实执行了子类版本,但此时子类字段还未初始化(仍是默认值)。
class Parent {
String value = "parent";
Parent() {
init(); // 这里会调到 Child.init()
}
void init() { System.out.println("Parent init"); }
}
class Child extends Parent {
String value = "child";
Child() { super(); }
@Override
void init() { System.out.println(value); } // 打印 null!
}
这是因为子类构造器还没开始执行,value 字段尚未赋值。
protected 或 public 方法final 方法(无法被重写)或静态工厂模式绕过