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

按照调用堆栈:

  • 新的 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 回答
5

构造函数有些特殊——除了 之外Object(),任何类中的每个构造函数都必须调用一个,并且只能调用一个其他构造函数,无论是在当前类还是它的超类中,然后才能运行其中的任何其他代码。您可以通过使用或来明确选择 this 是哪个构造函数。如果你不这样做,那么只有这样超类的无参数构造函数才会被隐式调用。(好像你用过。)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()不会被调用,因为既没有构造函数Circle9也没有GeometricObject(String,boolean)调用(“依赖于”)它——它们都显式地调用了其他构造函数。

于 2013-09-13T00:23:11.390 回答
4

Circle9 类的无参数构造函数打印 C,而不是 A。

您的通话顺序是: 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");

GeometricObject() 永远不会被调用;如果 GeometricObject(String, boolean) 显式调用this()它的第一行,您会看到 A,但默认情况下它不会从另一个构造函数调用。(必须调用构造函数来生成对象,但不需要从有参数的构造函数调用无参数构造函数,反之亦然。)

于 2013-09-13T00:10:03.397 回答
1

在这种情况下,Circle9类的空构造函数调用Circle9类的double构造函数,该构造函数调用Circle9类的半径、String、布尔构造函数,该构造函数调用GeometricObject类的String、布尔超构造函数。然后,当函数返回 - B(几何对象),E - 第三个圆 9,D - 第二个圆 9,C - 第一个圆 9 时,这会向后工作。

于 2013-09-13T00:08:32.437 回答
1

这个问题实际上与抽象类或接口没有任何关系。更多的是关于继承。

你的答案是这样的。当您调用子类时,首先调用它的超类,使用它们的无参数构造函数,除非您显式调用您拥有的不同构造函数。你打电话时:

Circle9()

哪个

this(1.0)

来电

Circle(doubleradius)

哪个

this(radius, "white", false)

来电

Circle(double, string, boolean)

哪个

super(Color, filled)

来电

GeometricObject(string, boolean)

这是继承链中的最后一个,所以它的动作首先执行

print("B")

然后程序通过链向后运行并根据链中的位置打印其余部分,它向前移动的方式相同,它向后移动的方式相同,因此

print("E")
print("D")
print("C")
于 2013-09-13T00:17:26.533 回答
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 回答