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)

なぜ例外があるのNullPointerExceptionか​​ 理解できません。stackTrace誰でも私が理解するのを助けることができますか?

コードはこちらで確認できます。

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. 派生コンストラクタ --> これはバーを初期化する場所です

ランタイム ポリモーフィズムにより、No. 4 でが呼び出されたとき、Derivedはまだ値に初期化されていません(初期化は No. 6 で行われるため)、NPE が発生します。method()bar"bar"

于 2013-04-13T10:06:03.143 に答える