超类型变量调用子类型方法及静态与重写方法输出差异的疑问
为什么静态方法与重写实例方法的调用结果不同?
嘿,这个问题问到点子上了!核心原因其实是Java里静态方法和实例方法的调用绑定机制完全不一样,咱们掰开揉碎了说:
1. 静态方法:编译期静态绑定,看「引用变量的类型」
静态方法本质上是属于类的,不属于任何具体对象。所以当你用超类型变量指向子类型对象时,调用静态方法的逻辑在编译阶段就确定了——JVM只会看你声明的变量类型是什么,完全不管这个变量实际指向的对象是谁。
举个简单例子:
class Parent { public static void show() { System.out.println("Parent static method"); } } class Child extends Parent { public static void show() { System.out.println("Child static method"); } } // 测试代码 Parent p = new Child(); p.show(); // 输出 "Parent static method"
这里变量p的类型是Parent,所以编译时就绑定了Parent的静态方法,哪怕实际对象是Child也没用。而且注意:子类的静态方法不是「重写」父类的,只是隐藏了父类的同名静态方法,这是完全不同的概念。
2. 重写的实例方法:运行期动态绑定,看「实际对象的类型」
而实例方法的重写是Java多态的核心,它的调用逻辑是在运行阶段才确定的——JVM会去看变量实际指向的那个对象是什么类型,然后调用该类型中被重写的方法。
还是用刚才的例子改一改:
class Parent { public void show() { System.out.println("Parent instance method"); } } class Child extends Parent { @Override public void show() { System.out.println("Child instance method"); } } // 测试代码 Parent p = new Child(); p.show(); // 输出 "Child instance method"
这里变量p虽然声明是Parent,但实际指向的是Child对象,所以运行时JVM会找到Child中重写的show()方法执行,这才是多态的体现。
为什么两者结果不一样?
简单来说:
- 静态方法是「类层面」的调用,和对象无关,所以看变量类型;
- 重写的实例方法是「对象层面」的调用,为了实现多态,所以看实际对象类型。
这就是为什么你看到的输出会有差异——重写方法的设计目的就是让同一个调用在不同对象上有不同表现,和静态方法的绑定逻辑完全相反,自然结果不会一致啦。
内容的提问来源于stack exchange,提问作者psFreak
相关产品推荐
相关产品推荐

