0

コンストラクターの呼び出しsuper()は、コンストラクターの最初の行にする必要がありますか? もしそうなら、なぜですか?コンストラクターのパラメーターの計算など、コンストラクターを呼び出す前に単純な制限付きの計算を実行できないのはなぜですか?

クロージャー仕様で呼び出すことができる内部クラスコンストラクターの状況を見つけました:

class A {
    class Inner1 {
        Inner1() {
            // do something
        }
    }
}

class B {
    A a1 = new A();
    A a2 = new A();

    class Inner2 extends A.Inner1 {
         Inner2(boolean sel) {
             (sel?a1:a2).super();
         }
    }

}

このケースは、基底クラス コンストラクターの外側のインスタンスを選択できることを示しています。選択ロジックをそれほど制限する必要があるのはなぜですか? なんでこんなの書けないんだ

if( sel ) {  
    a1.super();
}
else {
    a2.super();
}

添加

私の質問は、次のような場合に制限が発生する可能性があることを意味します。

public class Base {

private final String content;

public Base(String content) {
    this.content = content;
}

public String getContent() {
    return content;
}

}


public class Derived extends Base {

public Derived(String content) {
    super(String.format("Current value of content is %s.", getContent()));
}


}

後者の場合、私は:

super()1)最前列の条件を満たす

2) 工事順序違反

3) コンパイラ エラー「明示的にコンストラクターを呼び出している間はインスタンス メソッドを参照できません」が発生する

では、なぜ「最初の行の要件」を廃止して、最後のエラーのようなエラーだけに頼ることができないのでしょうか?

4

2 に答える 2

3

はい、super()コンストラクターの最初の呼び出しとして への呼び出しが必要です。

これを省略すると、コンパイラが呼び出しを挿入 (しようとする) するほどです。その理由を理解するには、Java の設計者の哲学を理解する必要があります。ゴスリングは常に、部分的に初期化されたオブジェクトへのアクセスがコンピューター プログラムのバグの大きな原因の 1 つだと考えるコンピューター科学者の陣営に属していました。そのため、彼はこの問題を軽減するのに役立つ厳密な初期化階層を設計しました。哲学に同意するかどうかは議論の余地がありますが、たとえば、参照とポインター、または実際の境界付き配列と同じくらい重要な Java の概念であることを理解することが重要です。いつでも初期化を呼び出すことができる Objective C のような言語でさえ、初期化チェーンを強制するために多大な時間を費やしていることに注意してください。ただし、厳密な言語規則とは対照的に、規則に従って行う必要があります。

あなたの例で何を説明しようとしていたのかわかりませんが、Java で何年にもわたって開発した後、スーパーを呼び出す前にロジックを実行する必要がある多くのケースが見つかるとは思えません。

于 2012-05-23T21:52:08.050 に答える
0

コンストラクター呼び出しは、そのクラスのコンストラクターが呼び出される前に呼び出される、階層内のすべてのクラスのスーパーで連鎖されます。Java のすべてのクラスはオブジェクト クラスから継承されるため、Object クラスのコンストラクターは、オブジェクトのメモリ割り当てが Object クラスのコンストラクターによって行われるという理由で、すべてのクラスに対して最初に呼び出されます。

于 2012-05-23T20:53:32.193 に答える