5

可能重复:
为什么 this() 和 super() 必须是构造函数中的第一个语句?

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

4

4 回答 4

18

他们没有。

如果不显式调用超构造函数,则相当于调用无参数超构造函数。

public class Sub
{
    public Sub()
    {
        // Do some stuff
    }
}

相当于:

public class Sub
{
    public Sub()
    {
        super();
        // Do some stuff
    }
}

如果指定参数,则必须显式调用超级构造函数。这很合理,IMO——你真的想让编译器猜测你想提供哪些参数吗?

于 2013-01-10T03:43:59.463 回答
2

子类甚至隐式调用非参数化的超类中存在的默认构造函数。当我们将参数传递给构造函数时,我们必须显式调用。

于 2013-01-10T04:02:57.293 回答
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直接创建 a,则必须指定人员的motherand father,并且该hasAnyLivingParents()方法期望指定这些。

现在,假设您有一个子类 Employee,并且您不关心 Employee 的父母,因此您想编写如下内容:

class Employee extends Person {
    double salary;

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

这不会编译,因为我们没有调用 的构造函数Person,并且没有默认构造函数。如果这确实编译,调用总是(new Employee(50000d)).hasAnyLivingParents()会抛出一个,因为甚至没有初始化and字段。NullPointerExceptionmotherfather

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

于 2013-01-10T04:05:22.267 回答
1
class Parent
{ 
   Parent(int x) {}
}

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

编译器尝试super()作为构造函数的第一行调用,Child()但父级没有无参数构造函数。因此,在这种情况下,您必须通过调用来明确地执行此操作super(5),例如。

于 2013-01-10T03:48:41.183 回答