可能重复:
Why does this() and super() have to be the first statement in a constructor?
为什么子类构造函数必须显式调用超类构造函数?这是什么原因?
答案 0 :(得分:17)
他们没有。
如果没有显式调用超级构造函数,则相当于调用无参数的超构造函数。
public class Sub
{
public Sub()
{
// Do some stuff
}
}
相当于:
public class Sub
{
public Sub()
{
super();
// Do some stuff
}
}
如果要指定参数,do 显式必须调用超级构造函数。这是非常合理的,IMO - 你真的希望编译器猜测你想提供哪些参数?
答案 1 :(得分:2)
子类隐式调用甚至超类中存在的默认构造函数,该构造函数是非参数化的。 当我们将参数传递给构造函数时,我们必须显式调用。
答案 2 :(得分:2)
如上所述,如果父类中没有默认构造函数,则只需调用超级构造函数。
这是必需的,因为父类必须由其构造函数之一初始化,如果没有默认构造函数,则java编译器无法知道要调用哪个构造函数,或者需要传递哪些参数。
为了更好地理解为什么必须调用父级中的至少一个构造函数,请考虑以下内容:
class Person {
private Person mother;
private Person father;
public Person(Person mother, Person father) {
assert mother != null && father != null: "Parents can't be null!";
this.mother = mother;
this.father = father;
}
public boolean hasAnyLivingParents() {
return mother.isAlive() || father.isAlive();
}
public boolean isAlive() { return true; }
}
如果您直接创建Person
,则必须指定此人的mother
和father
,hasAnyLivingParents()
方法需要指定这些内容。
现在,考虑一下你有一个子类Employee,你不关心Employee的父母,所以你想写这样的东西:
class Employee extends Person {
double salary;
public Employee(double salary) {
this.salary = salary;
}
}
这不会编译,因为我们不调用Person
的构造函数,并且没有默认构造函数。如果 进行编译,则调用(new Employee(50000d)).hasAnyLivingParents()
将总是抛出NullPointerException
,因为甚至没有任何内容初始化mother
和{{1} } fields。
简而言之,java 要求每个类都由一些构造函数初始化。如果类上没有默认构造函数,则必须调用其中一个构造函数才能初始化该对象。
答案 3 :(得分:1)
class Parent
{
Parent(int x) {}
}
class Child extends Parent
{
Child(){} // will not compile.
}
编译器尝试调用super()
作为Child()
构造函数的第一行,但父编译器没有 no-arg构造函数。因此,在这种情况下,您必须通过调用super(5)
来明确地执行此操作。