5

Thinking in Java からこの例を理解しようとしています:

package c07;
import com.bruceeckel.simpletest.*;

class Meal {
    Meal() { System.out.println("Meal()"); }
}

class Bread {
    Bread() { System.out.println("Bread()"); }
}

class Cheese {
    Cheese() { System.out.println("Cheese()"); }
}

class Lettuce {
    Lettuce() { System.out.println("Lettuce()"); }
}

class Lunch extends Meal {
    Lunch() { System.out.println("Lunch()"); }
}

class PortableLunch extends Lunch {
    PortableLunch() { System.out.println("PortableLunch()");}
}

public class Sandwich extends PortableLunch {
    private static Test monitor = new Test();
    private Bread b = new Bread();
    private Cheese c = new Cheese();
    private Lettuce l = new Lettuce();

    public Sandwich() {
        System.out.println("Sandwich()");
    }

    public static void main(String[] args) {
        new Sandwich();
        monitor.expect(new String[] {
          "Meal()",
          "Lunch()",
          "PortableLunch()",
          "Bread()",
          "Cheese()",
          "Lettuce()",
          "Sandwich()"
        });
    }
}

Java 言語仕様からわかるように、実行の順序は main メソッドを含むクラスをロードすることから始まります。次に、このクラスのすべての静的変数とメンバー変数を初期化する必要があります (その前に、スーパークラスのすべてのメンバー変数を初期化する必要がありますが、この場合はありません)。

だから、、、実行を開始する前に初期化されるbc思いました。ただし、出力からはそうではないようです。何か不足していますか?lmain

4

3 に答える 3

5

いいえ、bインスタンス変数ですc

を含むクラスの自動インスタンス化はありませんmain静的変数のみが初期化されます。外部の呼び出し元が次のように書いているかのようです。

Sandwich.main(args);

だからあなたが書いたとき:

次に、このクラスのすべての静的変数とメンバー変数を初期化する必要があります

...それは間違っていました。通常どおり、静的変数のみが初期化されます。

于 2012-10-02T18:40:32.683 に答える
0

JLS#12.4.1。初期化が発生したとき

クラスまたはインターフェイスタイプTは、次のいずれかが最初に発生する直前に初期化されます。

  • Tはクラスであり、Tのインスタンスが作成されます。
  • Tはクラスであり、Tによって宣言された静的メソッドが呼び出されます。
  • Tによって宣言された静的フィールドが割り当てられます。
  • Tによって宣言された静的フィールドが使用され、フィールドは定数変数ではありません(§4.12.4)。
  • Tはトップレベルクラス(§7.6)であり、T(§8.1.3)内に字句的にネストされたassertステートメント(§14.10)が実行されます。

JLS#12.5。新しいクラスインスタンスの作成

新しいクラスインスタンスが作成されるたびに、クラスタイプで宣言されたすべてのインスタンス変数と、クラスタイプの各スーパークラスで宣言されたすべてのインスタンス変数(非表示になっている可能性のあるすべてのインスタンス変数を含む)のためのスペースを備えたメモリスペースが割り当てられます( §8.3)。

于 2012-10-02T18:45:48.857 に答える
0

出力例は正しいです。重要なルールは次のとおりです。

  • クラスが作成されるとき、スーパークラスのコンストラクターを最初に呼び出す必要があります。これはObjectクラスまで泡立ちます

  • コンストラクターが呼び出される前に、メンバー変数の初期化が呼び出されます。

staticこの例には、技術的な を除いて、 は含まれていませんmonitor

于 2012-10-02T18:41:37.833 に答える