为什么子类构造函数必须显式调用超类构造函数?
可能重复:
为什么this()和super()必须是构造函数中的第一个语句?
为什么子类构造函数必须显式调用超类构造函数? 这是什么原因?
他们没有。
如果没有显式调用超级构造函数,那么它等同于调用无参数的超构造函数。
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
,则必须指定person的father
和father
,并且hasAnyLivingParents()
方法需要指定这些人员。
现在,考虑你有一个子类,Employee,你不关心Employee的父母,所以你想写这样的东西:
class Employee extends Person { double salary; public Employee(double salary) { this.salary = salary; } }
这将无法编译,因为我们不调用Person
的构造函数,并且没有默认构造函数。 如果这确实编译,则调用(new Employee(50000d)).hasAnyLivingParents()
将始终抛出NullPointerException
,因为甚至没有初始化mother
和father
字段。
简而言之,java 要求每个类都由一些构造函数初始化。 如果类上没有默认构造函数,则必须调用其中一个构造函数才能初始化该对象。
class Parent { Parent(int x) {} } class Child extends Parent { Child(){} // will not compile. }
编译器尝试调用super()
作为Child()
构造函数的第一行,但父编译器没有no-arg构造函数 。 因此,在这种情况下,您必须通过调用super(5)
显式地执行此操作。