为什么子类构造函数必须显式调用超类构造函数?这是什么原因?
4 回答
他们没有。
如果不显式调用超构造函数,则相当于调用无参数超构造函数。
public class Sub
{
public Sub()
{
// Do some stuff
}
}
相当于:
public class Sub
{
public Sub()
{
super();
// Do some stuff
}
}
如果要指定参数,则必须显式调用超级构造函数。这很合理,IMO——你真的想让编译器猜测你想提供哪些参数吗?
子类甚至隐式调用非参数化的超类中存在的默认构造函数。当我们将参数传递给构造函数时,我们必须显式调用。
如上所述,如果父类中没有默认构造函数,则只需调用超级构造函数。
这是必需的,因为父类必须由其构造函数之一初始化,如果没有默认构造函数,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
直接创建 a,则必须指定人员的mother
and father
,并且该hasAnyLivingParents()
方法期望指定这些。
现在,假设您有一个子类 Employee,并且您不关心 Employee 的父母,因此您想编写如下内容:
class Employee extends Person {
double salary;
public Employee(double salary) {
this.salary = salary;
}
}
这不会编译,因为我们没有调用 的构造函数Person
,并且没有默认构造函数。如果这确实编译,调用总是(new Employee(50000d)).hasAnyLivingParents()
会抛出一个,因为甚至没有初始化and字段。NullPointerException
mother
father
简而言之,java要求每个类都由某个构造函数初始化。如果类上没有默认构造函数,则必须调用其其他构造函数之一才能初始化对象。
class Parent
{
Parent(int x) {}
}
class Child extends Parent
{
Child(){} // will not compile.
}
编译器尝试super()
作为构造函数的第一行调用,Child()
但父级没有无参数构造函数。因此,在这种情况下,您必须通过调用来明确地执行此操作super(5)
,例如。