3

我有这个代码片段:

class Base {
    public Base() {
        method();
    }

    void method() {
        System.out.println("In Base");
    }
}

class Derived extends Base {
    private String bar;

    public Derived() {
        bar="bar";
    }

    public void method() {
        System.out.println(bar.length());
    }

    public static void main(String[] args) {
        Base base=new Derived();
        base.method();
    }
}

在执行代码时出现异常:

Exception in thread "main" java.lang.NullPointerException
    at Derived.method(Main.java:22)
    at Base.<init>(Main.java:5)
    at Derived.<init>(Main.java:17)
    at Derived.main(Main.java:27)

我无法理解为什么会有例外NullPointerExceptionstackTrace任何人都可以帮助我理解吗?

你可以在这里查看代码。

4

2 回答 2

8

new Derived()创建一个Derived对象,这意味着首先调用它的超类构造函数,然后调用method- 但是你已经覆盖method了,所以它是被调用的那个方法的子版本。在该方法中,您调用bar.length尚未初始化的方法。

结论:在构造函数中调用可覆盖的方法几乎从来都不是一个好主意。

于 2013-04-13T09:51:11.463 回答
2

您给出的代码是一个反模式。我们永远不应该调用处理字段的方法constructor,原因很简单,因为它可能会产生意想不到的结果

从您的代码中,您正在尝试初始化构造函数中调用的bar字段Derived。现在,当您说时Base b = new Derived(),呼叫以下列方式发生

  1. 基本静态初始化器——如果你有
  2. 派生静态初始化器——如果你有

  3. 基本块初始化器——如果你有

  4. Base Constructor --> 这是你要调用的地方method()

  5. 派生块初始化器——如果你有

  6. 派生构造函数 --> 这是你初始化 bar 的地方

现在由于运行时多态性,到 4 号,当Derived'method()被调用时,bar还没有初始化为值"bar"(因为初始化发生在 6 号),NPE 发生

于 2013-04-13T10:06:03.143 回答