假设我们有以下代码:
class A {
public void doLogic() {
System.out.println("doLogic from A");
}
}
class B extends A {
@Override
public void doLogic() {
System.out.println("doLogic from B");
}
public void doDifferentLogic() {
System.out.println("doDifferentLogic from B");
super.doLogic();
}
}
class C extends B {
@Override
public void doLogic() {
System.out.println("doLogic from C");
}
}
public class Test {
public static void main(String[] args) {
C c = new C();
c.doDifferentLogic();
}
}
当我们执行这段代码时,预期的行为如下:
由于 c 持有对 C 类对象的引用,因此当您调用 c.doDifferentLogic()
方法时,JVM 会在 C 类中搜索该方法,并且由于找不到它,它开始查看继承树。正如预期的那样,doDifferentLogic()
方法在父类(super class)中找到并执行。然而,构造 super.doLogic()
应该从当前的引用“Point of View”来看,它是 C 类型的。所以 C 的 super 应该是 B,而是从顶部开始的方法调用 A 类。
如果您删除 super
关键字,或将其替换为 this
关键字(与“this”是隐式的相同),您将获得预期的多态行为并调用 C 类中的 doLogic()
。
所以我的问题是:
应该调用 super.doLogic()
是 this.super.doLogic()
(2),而不是 static.super.doLogic()
(1) ?
两者都是无效的结构,他们在这里只是为了更好地解释自己。
(1) 或者换句话说 - 从对当前对象 c 的引用中,获取当前对象的父类(super class)并调用 doLogic()
方法而不是
(2)从这个类中获取父类(super class)并调用它的doLogic()
方法?
最佳答案
在 Java 中,super
关键字总是指使用该关键字的类型的父类(super class),而不是调用该方法的对象的动态类型的父类(super class)。换句话说,super
是静态解析的,而不是动态解析的。这意味着在 B
类的上下文中,super
关键字总是指代 A
类,而不管 B
方法使用 C
对象作为接收者来执行。据我所知,没有办法在不使用反射的情况下动态确定父类(super class)类型并使用其方法。
希望这会有所帮助!
关于java - Java中的 super 关键字,有趣的行为,请解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22048684/