我有以下两个班级
public class classA {
classA() {
System.out.println("A");
}
}
class classB extends classA {
classB() {
System.out.println("B");
}
}
然后运行
classA c = new classB();
或
classB c = new classB();
总是给出
A
B
为什么会这样?乍一看,在任何一种情况下,我都会假设只调用classB
构造函数,因此唯一的输出是
B
但这显然是错误的。
答案 0 :(得分:25)
这就是Java的工作原理。在调用子类的构造函数之前,通过Object
调用父类的构造函数,直到类层次结构。
引自the docs:
使用
super()
,调用超类无参数构造函数。使用super(parameter list)
,将调用具有匹配参数列表的超类构造函数。注意: 如果构造函数没有显式调用超类构造函数,Java编译器会自动插入对超类的无参数构造函数的调用 < / strong>即可。如果超类没有无参数构造函数,则会出现编译时错误。
Object
确实有这样的构造函数,所以如果Object
是唯一的超类,则没有问题。如果子类构造函数显式或隐式地调用其超类的构造函数,您可能会认为将调用整个构造函数链,一直回到
Object
的构造函数。事实上,情况就是这样。它被称为构造函数链接,当有很长的类下降时你需要注意它。
答案 1 :(得分:6)
在构造过程中总是调用超类构造函数,并且保证在调用子类构造函数之前完成超类构造。对于大多数(如果不是全部)面向对象语言来说就是这种情况。如果您不想调用默认构造函数,可以使用参数显式调用超类构造函数;否则这样的调用由编译器自动完成。
答案 2 :(得分:2)
在构造的对象方面,两个语句没有区别,因此您可以看到相同的输出。
在使用new
构建相同对象时,只需在左侧使用不同的引用类型就对象创建和构造函数链接而言不会有任何区别。
两个语句之间的差异是在创建对象之后。