我一直在学习继承,我只是好奇。我知道即使你不使用super()
运算符,子类也会自动调用超类的构造函数,所以我想知道子类是否有必要使用构造函数它
答案 0 :(得分:14)
如果超类没有默认构造函数(或者具有子类无法访问的构造函数),则子类需要构造函数。如果子类根本没有构造函数,编译器将自动创建一个public
构造函数,它只是调用超类的默认构造函数。
关于调用super()
:每个构造函数必须做的第一件事是通过调用this()
(可能带有一些参数)调用同一个类中的不同构造函数,或者通过调用调用其超类的构造函数super()
(再次,可能有参数)。这些电话都不能去其他任何地方。如果构造函数不以任何一个开头,编译器将自动插入对super()
的调用(不带任何参数)。因此,如果您想要的行为是调用默认的超类构造函数(并且很多时候都是这样),那么您不需要自己明确地调用super()
。
即使超类没有默认构造函数,也有一种情况是你不需要提供构造函数(事实上,你不能提供构造函数)。这种情况(在section 15.9.5.1 of the Java Language Sepcification中描述)是使用非默认构造函数创建类的匿名子类时;编译器将自动创建具有正确参数的构造函数,并调用相应的(非默认)超类构造函数。例如:
class X {
public X(int value) { ... } // no default constructor!
public void foo() { ... }
}
X myX = new X(3) {
@Override
public void foo() { ... }
};
然后myX
将是X的匿名子类的实例,其中包含编译器生成的构造函数,该构造函数接受int
参数并调用super(intArg)
。
因为无法为匿名类编写构造函数,所以会出现问题:如果在创建对象时需要进行一些对象初始化,该怎么办?解决方案是使用instance initializer block。例如:
X myX = new X(3) {
// Field unique to this subclass of X:
private int baz;
{
// code here runs as if it were at the start of every constructor
baz = ...;
}
@Override
public void foo() { ... }
};
答案 1 :(得分:2)
如果通过super()访问的默认超类构造函数可用,则子类不需要具有显式构造函数;它将自动获得默认的无参数构造函数。如果超类具有显式构造函数,所有构造函数都接受参数,那么子类也需要一个显式构造函数,因为如果没有这样的构造函数,就无法知道应该调用超类构造函数的参数。
答案 2 :(得分:2)
如果超类没有默认(即没有args)构造函数,那么必须定义一个调用特定超级构造函数的构造函数。
如果超类 有默认构造函数,则不必声明构造函数,因为如果你没有为你定义隐式的构造函数不要声明任何构造函数:
SubClass() {
super(); // Note: the no-args super constructor may itself be implicit
}
因此,在这种情况下,您不必在子类中声明构造函数。
答案 3 :(得分:0)
如果默认构造函数在超类中可用,则编译器将在子类的默认构造函数中包含默认构造函数调用。例如 -
class Base(){
Base(){ // default constructor
...
}
}
class Sub extends Base{
// no constructor
}
在这种情况下不需要。
class Base(){
Base( int i){ // no default constructor
...
}
}
class Sub extends Base{
// no constructor
}
在这种情况下需要它。
class Sub extends Base{
Sub(){
Base(1);
}
}