为什么子类构造函数必须显式调用超类构造函数?

可能重复:
为什么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的fatherfather ,并且hasAnyLivingParents()方法需要指定这些人员。

现在,考虑你有一个子类,Employee,你不关心Employee的父母,所以你想写这样的东西:

 class Employee extends Person { double salary; public Employee(double salary) { this.salary = salary; } } 

这将无法编译,因为我们不调用Person的构造函数,并且没有默认构造函数。 如果这确实编译,则调用(new Employee(50000d)).hasAnyLivingParents()始终抛出NullPointerException ,因为甚至没有初始化motherfather字段。

简而言之,java 要求每个类都由一些构造函数初始化。 如果类上没有默认构造函数,则必须调用其中一个构造函数才能初始化该对象。

 class Parent { Parent(int x) {} } class Child extends Parent { Child(){} // will not compile. } 

编译器尝试调用super()作为Child()构造函数的第一行,但父编译器没有no-arg构造函数 。 因此,在这种情况下,您必须通过调用super(5)显式地执行此操作。