Java - 子类调用 super 构造函数,它调用子类方法而不是它自己的方法

标签 java inheritance methods constructor overriding

我将从一个代码示例开始:

class A {
    public A() {
        f(); //When accessed through super() call this does not call A.f() as I had expected.
    }

    public void f() {} //I expect this to be called from the constructor.
}

class B extends A {
    private Object o;

    public B() {
        super();
        o = new Object(); //Note, created after super() call.
    }

    @Override
    public void f() {
        //Anything that access o.
        o.hashCode(); //Throws NullPointerException.
        super.f();
    }
}

public class Init {
    public static void main(String[] args) {
        B b = new B();
    }
}

这个程序抛出一个 NullPointerException .当对象 b 进入其父类(super class)的构造函数时 A并调用方法 f()被 B 类覆盖 B.f()被调用,而不是 A.f()我会预料到的。

我认为父类(super class)不应该知道它是否被子类化,但类肯定可以使用它来判断它是否被子类化吗?这背后的原因是什么?如果我真的想要,有什么解决方法吗 A.f()被调用而不是 B.f()

提前致谢。


跟进问题:

感谢您的回答。我现在明白为什么会这样了,但这是一个后续问题。也许我错了,但子类型化的原则是父类(super class)型不应该知道它已被子类型化。这种“机制”让一个类知道它是否被子类化。考虑这个代码示例:

class A {
    private boolean isSubclassed = true;

    public A() {
        f(); //A.f() unsets the isSubclassed flag, B.f() does not.
        if(this.isSubclassed) {
            System.out.println("I'm subclassed.");
        } else {
            System.out.println("I'm not subclassed.");
        }
    }

    public void f() {
        this.isSubclassed = false;
    }
}

class B extends A {
    public B() {
        super();
    }

    @Override
    public void f() {}
}

public class Init {
    public static void main(String[] args) {
        new B(); //Subclass.
        new A();
    }
}

这个程序的输出是:

I'm subclassed.
I'm not subclassed.

在这里A知道它已被子类化。不知道是谁干的,但这并不重要。这怎么解释?我被误导了吗?

最佳答案

NullPointerException 的发生是因为当您构造 B 的实例时,将调用父构造函数(在 A 中)。此构造函数调用 f() 方法,但由于对象的实际类型是 B,因此调用 B 中重写的 f() 方法。

@Override
public void f() {
    //Anything that access o.
    o.hashCode(); //Throws NullPointerException as o has not been initialised yet
    super.f();
}

这里的教训是永远不要在构造函数中调用可以被子类覆盖的方法。

关于Java - 子类调用 super 构造函数,它调用子类方法而不是它自己的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20116961/

相关文章:

java - 从二维数组创建距离矩阵

c++ - 双指针对象数组 - 克隆元素

java - Hashmap方法求和

javascript - 替换字符串中的值

java - 反转句子中的每第二个单词

java - 如何从 Java 编辑 xsl 标签属性文件

asp.net-mvc - ASP.NET MVC : Ignore custom attribute in a base controller class

java - 尝试使用 void 方法中的实例变量 (java)

Java:直接从同一类的另一个实例访问私有(private)字段

java - 从方法中的字符串到类中的字符串