1. 概述

在这个教程中,我们将深入探讨Java中的“隐式超类构造函数未定义”错误。首先,我们将创建一个产生此错误的例子。接下来,我们将解释异常的主要原因,并了解如何修复它。

2. 实践示例

现在,让我们看一个导致编译错误“隐式超类构造函数X()未定义。必须显式调用另一个构造函数”的例子。

在这里,X 表示任何看到此错误的子类所继承的父类。

首先,我们创建一个父类 Person

public class Person {

    String name;
    Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

   // setters and getters
}

现在,我们创建一个父类为 Person 的子类 Employee

public class Employee extends Person {

    Double salary;

    public Employee(String name, Integer age, Double salary) {
        this.salary = salary;
    }

    // setters and getters
}

在我们的IDE中,我们会看到错误:

Implicit super constructor Person() is undefined. Must explicitly invoke another constructor

在某些情况下,如果子类没有构造函数,我们也可能会遇到类似错误。

例如,考虑没有构造函数的 Employee

public class Employee extends Person {

    Double salary;

    // setters and getters
}

在IDE中,我们会看到错误:

Implicit super constructor Person() is undefined for default constructor. Must define an explicit constructor

3. 原因

在Java继承中,构造函数链式调用是指使用 super 方法调用父类的构造函数序列。子类构造函数必须明确或隐式地调用超类构造函数。无论如何,都需要定义一个超类构造函数。

如果没有父类的类,其父类将是 Object 类。Java中的 Object 类有一个无参数的构造函数。

当一个类没有构造函数时,编译器会自动添加一个无参数的默认构造函数,并在第一条语句中插入对 super 的调用——这会调用 Object 类的构造函数。

假设我们的 Person 类没有任何构造函数,也没有父类。一旦编译,我们可以看到编译器已添加了默认的无参构造函数:

public Person() {
    super();
}

相反,如果 Person 类中已经有了构造函数,编译器不会自动添加这个无参数的默认构造函数。

现在,如果我们创建一个扩展 Person 的子类 Employee,在 Employee 类中会出现错误:

Implicit super constructor Person() is undefined for default constructor. Must define an explicit constructor

因为编译器会在 Employee 构造函数中插入对 Employee 构造函数的 super 调用,它将找不到 Person 类中没有参数的构造函数。

4. 解决方案

要解决这个问题,我们需要向编译器提供明确的信息。

首先,我们需要在 Employee 构造函数中明确调用 super 构造函数:

public Employee(String name, Integer age, Double salary) {
    super(name, age);
    this.salary = salary;
}

现在,假设我们需要创建一个只有 salary 字段的 Employee 对象。我们可以编写构造函数:

public Employee(Double salary) {
    super();
    this.salary = salary;
}

尽管我们在 Employee 构造函数中添加了 super 调用,但我们仍然会收到错误,因为 Person 类仍然缺少匹配的构造函数。 我们可以通过在 Person 类中显式创建一个无参数构造函数来修复这个问题:

public Person(String name, Integer age) {
    this.name = name;
    this.age = age;
}

public Person() {
}

最后,由于这些更改,我们不会再遇到编译错误。

5. 总结

我们已经解释了Java的“隐式超类构造函数未定义”错误。然后,我们讨论了如何产生这个错误以及异常的原因。最后,我们讨论了解决该错误的方法。

如往常一样,本文的示例代码可在GitHub上找到:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-lang-oop-constructors/


» 下一篇: Java Weekly, 第416期