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

时间:2013-01-10 03:42:48

标签: java

  

可能重复:
  Why does this() and super() have to be the first statement in a constructor?

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

4 个答案:

答案 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,则必须指定此人的motherfatherhasAnyLivingParents()方法需要指定这些内容。

现在,考虑一下你有一个子类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)来明确地执行此操作。