更多内容请看我的个人网站
成员变量:编译看左边,运行看左边
成员方法:编译看左边,运行看右边
在编译时(静态绑定),成员变量是根据引用类型(也就是声明的类型)来决定的;
在运行时(动态绑定),方法是根据对象的实际类型(也就是 new 出来的类型)来决定的。
class Parent {
public String name = "Parent";
public void sayHi() {
System.out.println("Hi from Parent");
}
}
class Child extends Parent {
public String name = "Child";
@Override
public void sayHi() {
System.out.println("Hi from Child");
}
}
public class Test {
public static void main(String[] args) {
Parent obj = new Child();
System.out.println(obj.name); // 输出:Parent
obj.sayHi(); // 输出:Hi from Child
}
}
Java 对成员变量的访问是静态绑定的。也就是说:
编译器在编译阶段就决定了访问的是哪个变量。
因为 obj
是 Parent
类型的引用,所以直接去找 Parent.name
,不管你指向的是 Child
对象。
✅ 所以访问的是
Parent
中的name
,输出Parent
。
Java 中的方法调用(如果是 非 static
的实例方法)是动态绑定的,也就是说:
编译时只检查你有没有这个方法。
运行时会看真实的对象是谁,再调用那个类中“最合适的版本”。
✅ 所以
obj.sayHi()
实际运行的是Child
中的重写方法,输出Hi from Child
。
成员 | 绑定方式 | 决定于 | 行为 |
---|---|---|---|
变量 | 静态绑定 | 引用类型 | 看“左边” |
方法 | 动态绑定 | 实际对象 | 看“右边” |