java - Java中的 super 关键字,有趣的行为,请解释

标签 java inheritance super

假设我们有以下代码:

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/

相关文章:

java - Java Netbeans 变量继承问题

python - python 2.7.x 中的继承

java如何制作带有垂直文本的JLabel?

C++有没有可能让一个类扩展一个类,同时又是一个接口(interface)的实现?

java - Google App Engine 搜索 API 给予某些字段比其他字段更高的优先级

c# - 如何避免 GUI 控件和域对象之间的并行继承层次结构

c++ - 在接口(interface)不是时标记派生实现 noexcept 的副作用是什么

ruby - 使用 'super' 的 ruby​​ 中不合逻辑的 : circle of logic,

java - 带 EditText 和 InputType 电子邮件的 AlertDialog - Android

java - 让计算器上的按钮具有交互性(以便它们实际上可以加、减等)的最佳方法是什么?