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

Why exactly do subclass constructors have to explicitly call super class constructors?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why does this() and super() have to be the first statement in a constructor?

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


他们没有。

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

1
2
3
4
5
6
7
public class Sub
{
    public Sub()
    {
        // Do some stuff
    }
}

相当于:

1
2
3
4
5
6
7
8
public class Sub
{
    public Sub()
    {
        super();
        // Do some stuff
    }
}

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


如上所述,如果父类中没有默认的构造函数,则只需调用一个超级构造函数。

这是必需的,因为父类必须由其构造函数中的一个初始化,如果没有默认构造函数,Java编译器就不知道要调用哪个构造函数,或者需要传递哪些参数。

为了更好地理解为什么必须调用父级中的至少一个构造函数,请考虑以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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,则必须指定人员的motherfather,并且hasAnyLivingParents()方法希望指定这些内容。

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

1
2
3
4
5
6
7
class Employee extends Person {
    double salary;

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

这不会编译,因为我们不调用Person的构造函数,也没有默认的构造函数。如果这样编译,调用(new Employee(50000d)).hasAnyLivingParents()总是抛出NullPointerException,因为甚至没有初始化motherfather字段。

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


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


1
2
3
4
5
6
7
8
9
class Parent
{
   Parent(int x) {}
}

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

编译器试图调用super()作为Child()构造函数的第一行,但父级没有arg构造函数。因此,在本例中,您必须通过调用super(5)来显式地执行此操作。