21
//: c07:Sandwich.java
// Order of constructor calls.
// package c07;
// import com.bruceeckel.simpletest.*;

import java.util.*;

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()"
    });
    // */
  }
} ///:~

このコードの出力は

Meal()
Lunch()
PortableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()  

クラス内のフィールドは宣言された順序で作成されるため、

Bread()
Cheese()
Lettuce()

上記のリストの一番上に来ますか?

また、このコードで何をしようとしていますか?

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

最初は匿名クラスかと思いましたが、そうではありません。文字列配列を初期化していますか? String 変数の名前がないのはなぜですか? ここで使われているプログラミング構造の名前を教えてください。

4

4 に答える 4

25

コンストラクター:

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

コンパイラによって次のように変換されます。

public Sandwich() {
    super();   // Compiler adds it if it is not explicitly added by programmer
    // All the instance variable initialization is moved here by the compiler.
    b = new Bread();
    c = new Cheese();
    l = new Lettuce();

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

したがって、コンストラクターの最初のステートメントは、スーパークラス コンストラクターの連鎖です。実際、コンストラクターの最初のステートメントは、スーパークラスのコンストラクターにチェーンされます。そのため、最初にスーパー クラス コンストラクターPortableLunchが呼び出され、コンパイラーによって追加されたために、呼び出しが再びスーパー クラス コンストラクターにチェーンsuper()されます (覚えていますか?)。

このコンストラクター呼び出しの連鎖は、継承階層の最上位のクラスまで行わObjectれるため、最後にクラス コンストラクターが呼び出されます。

これで、各スーパー クラス コンストラクターが実行され、すべてのスーパー クラス フィールドが初期化された後、直接のサブクラス コンストラクターが呼び出し後に実行を開始しsuper()ます。そして最後に、フィールドSandwitch()を初期化するコンストラクターに戻り3ます。

したがって、基本的にフィールドは最後に初期化されるため、最後に印刷される直前にSandwitch()印刷されます。

インスタンス作成プロセスの詳細な説明については、JLS - §12.5 - 新しいクラス インスタンスの作成を参照してください。


質問の2番目の部分については:

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

このコードは、名前のない配列を作成し、同時にいくつかの文字列リテラルを初期化しています。これは、名前付き配列を作成する方法に似ています。

String[] arr = new String[] { "rohit", "jain" };
于 2013-07-23T09:33:46.837 に答える
5

この例のオブジェクトは継承を使用しているため、コンストラクターのチェーンが呼び出されます。継承を使用する場合、別のクラスから継承するクラス ( subtype) は、継承するクラスのコンストラクターを呼び出す必要があります ( super type)。型階層が存在する場合、つまり複数のクラスがチェーン内で相互に拡張されている場合、スーパー コンストラクターの呼び出しは、別のクラスから継承されていないチェーン内の最初のクラスに伝達されます (Object は無視されます)。

サブタイプのスーパー クラス コンストラクターは、スーパー タイプのフィールドまたはメソッドに依存する可能性があるため、サブタイプのコンストラクターを実行する前に呼び出す必要があります。コンストラクター呼び出しは型階層を連鎖し、各コンストラクターが初期化されると、サブタイプのインスタンス化が開始されます。

クラス型階層のスーパー型コンストラクターが呼び出されると、サブタイプのコンストラクターによっても必要とされる可能性があるため、サブタイプのフィールドが宣言されます。サブタイプのフィールドが宣言された後、サブタイプ コンストラクターが実行されます。

サブタイプはスーパータイプで確立されたフィールドまたはメソッドに依存する可能性があるため、この順序が必要です。

Meal() (Top of Class Hierarchy, not including Object)
Lunch() (Extends Meal)
PortableLunch() (Extends Lunch)
Bread() (Field of lunch declared before constructor call)
Cheese() (Field of lunch declared before constructor call)
Lettuce() (Field of lunch declared before constructor call)
Sandwich() (Extends Portable Lunch)

これは、Java でのオブジェクト作成の非常に優れた概要です。

于 2013-07-23T09:30:32.613 に答える
1
new String[] {
      "Meal()",
      "Lunch()",
      "PortableLunch()",
      "Bread()",
      "Cheese()",
      "Lettuce()",
      "Sandwich()"
    }

\上記は無名配列宣言です。この場合、サイズを指定する必要はありません。

インスタンス変数を初期化する前に、すべてのスーパークラス コンストラクターが最初に呼び出されます。つまり、

注文--- >

  Object(), 
  all your superclass constructors,
  instance variables of this class in that order
于 2013-07-23T09:32:12.560 に答える