2

現在、抽象クラスとインターフェースの演習テストを行っており、この問題に遭遇しました:

  public class Test {
  public static void main(String[] args) {
    new Circle9();
  }
}

public abstract class GeometricObject {
  protected GeometricObject() {
    System.out.print("A");
  }

  protected GeometricObject(String color, boolean filled) {
    System.out.print("B");
  }
}

public class Circle9 extends GeometricObject {
  /** Default constructor */
  public Circle9() {
    this(1.0);
    System.out.print("C");
  }

  /** Construct circle with a specified radius */
  public Circle9(double radius) {
    this(radius, "white", false);
    System.out.print("D");
  }

  /** Construct a circle with specified radius, filled, and color */
  public Circle9(double radius, String color, boolean filled) {
    super(color, filled);
    System.out.print("E");
  }

}

出力が BEDC なのはなぜですか? new Circle9() は最初に Circle 9 クラスの引数なしのコンストラクターを呼び出し、A を出力し、次に他の文字を出力すると思っていましたが、コードのパスを理解するのに苦労しています。

4

6 に答える 6

5

コンストラクターはやや特殊です。例外としてObject()、クラス内の各コンストラクターは、現在のクラスまたはそのスーパークラス内の他のコードを実行する前に、1 つだけ呼び出す必要があります。またはを使用して、これが明示的にどのコンストラクタであるかを選択できます。これを行わないと、スーパークラスの引数なしのコンストラクターが暗黙的に呼び出されます。(あたかも を使用したかのように。)this(...)super(...)super()

newつまり、これは、呼び出しているコンストラクターから始まり、最終的に到達する必要がある依存関係チェーンと見なすことができますObject()。あなたの例では、このチェーンは次のようになります。

Circle9() => prints "C"
  |
  | (explicit)
  v
Circle9(double) => prints "D"
  |
  | (explicit)
  v
Circle9(double,String,boolean) => prints "E"
  |
  | (explicit)
  v
GeometricObject(String, boolean) => prints "B"
  |
  | (implicit)
  v
Object() => does nothing

次に、コンストラクターで実際のコードを実行し、このチェーンを逆方向にたどります。

"A"印刷されない理由はGeometricObject()、コンストラクターCircle9GeometricObject(String,boolean)それを呼び出す (「依存する」) こともないため、呼び出されないためです。それらはすべて、他のコンストラクターを明示的に呼び出します。

于 2013-09-13T00:23:11.390 に答える
5

コール スタックに従ってください。

  • new Circle9() は Circle9() を呼び出します
  • Circle9() は this(1.0) を呼び出します
  • Circle9(double) は this(radius, "white", false) を呼び出します
  • Circle9(double、String、boolean) は super(color、filled) を呼び出します
  • GeometricObject(String, boolean) は B を出力します
  • Circle9(double、String、boolean) は E を出力します
  • Circle9(double) プリント D
  • Circle9() は C を出力します
于 2013-09-13T00:55:53.000 に答える
4

Circle9 クラスの引数なしのコンストラクターは、A ではなく C を出力します。

電話の順番は次のとおりです。 new Circle9(); new Circle9(double); new Circle9(double, String, boolean); new GeometricObject(String, boolean); System.out.print("B"); System.out.print("E"); System.out.print("D"); System.out.print("C");

GeometryObject() が呼び出されることはありません。GeometryObject(String, boolean)this()が最初の行として明示的に呼び出された場合、A が表示されますが、デフォルトでは別のコンストラクターから呼び出されません。(オブジェクトを作成するにはコンストラクターを呼び出す必要がありますが、引数を持つコンストラクターから引数なしのコンストラクターを呼び出す必要はなく、その逆も必要ありません。)

于 2013-09-13T00:10:03.397 に答える
1

この場合、Circle9 クラスの空のコンストラクターは Circle9 クラスの double コンストラクターを呼び出します。このコンストラクターは、Circle9 クラスの radius、String、boolean コンストラクターを呼び出します。このコンストラクターは、String、GeometricObject クラスの boolean スーパー コンストラクターを呼び出します。これは、関数が B (ジオメトリ オブジェクト)、E - 3 番目の円 9、D - 2 番目の円 9、C - 1 番目の円 9 を返すように逆方向に機能します。

于 2013-09-13T00:08:32.437 に答える
0

呼び出しnew Circle9()は、引数なしのスーパークラス コンストラクターを呼び出さず、別の場所で実行されます。自分のコードを読んでください。

public Circle9() {
    this(1.0);  // calls to Circle(double radius) constructor, & on from there..
    System.out.print("C");
}
于 2013-09-13T00:04:56.917 に答える