抽象类:此代码的输出

时间:2013-09-12 23:59:54

标签: java eclipse

目前正在对抽象类和接口进行实践测试并遇到了这个问题:

  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?我以为新的Circle9()会首先调用Circle 9类的无参数构造函数,打印A,然后是其他字母,但我很难理解代码的路径。

6 个答案:

答案 0 :(得分:5)

构造函数有些特殊 - 除了Object()之外,任何类中的每个构造函数必须调用一个,并且只有一个其他构造函数,当前类或其超类,在其中的任何其他代码运行之前。您可以使用this(...)super(...)选择显式的构造函数。如果不这样做,那么只会隐式调用超类的no-args构造函数。 (就好像你使用了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)的构造函数都没有调用(“依赖于”) - 它们都是显式调用其他构造函数。

答案 1 :(得分:5)

按照调用堆栈:

  • new Circle9()调用Circle9()
  • Circle9()调用此(1.0)
  • Circle9(double)调用此(radius,“white”,false)
  • Circle9(double,String,boolean)调用super(color,filled)
  • GeometricObject(String,boolean)打印B
  • Circle9(double,String,boolean)打印E
  • Circle9(双)打印D
  • Circle9()打印C

答案 2 :(得分: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,但默认情况下不会从另一个构造函数中调用它。 (必须调用构造函数来创建对象,但不需要从具有参数的构造函数中调用no-args构造函数,反之亦然。)

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

你的回答是这样的。当你调用一个子类时,首先调用它们的超类,使用它们的no-arg consructor,除非你明确地调用了一个不同的构造函数。当你打电话时:

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")

答案 5 :(得分:0)

调用new Circle9()不会调用no-arg超类构造函数,它会在其他地方运行。阅读你自己的代码。

public Circle9() {
    this(1.0);  // calls to Circle(double radius) constructor, & on from there..
    System.out.print("C");
}