目前正在对抽象类和接口进行实践测试并遇到了这个问题:
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,然后是其他字母,但我很难理解代码的路径。
答案 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()
永远不会被调用,因为Circle9
和GeometricObject(String,boolean)
的构造函数都没有调用(“依赖于”) - 它们都是显式调用其他构造函数。
答案 1 :(得分:5)
按照调用堆栈:
答案 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");
}