1

我在 scjp 指南中阅读如下

事实上,你不能不调用对象的实际类类型的构造函数,还要调用它的每个超类的构造函数来创建一个新对象!

例如

public class Person{

}

public class Employee extends Person{
   public Employee(){
}
}

我没有创建 Person 实例,但它是合法的。

请为我解释一下,谢谢您的帮助。

4

6 回答 6

1

他们真正的意思是

  • 当您创建子类对象时,即调用它的构造函数,然后在内部调用超类构造函数
  • 这是因为对于默认的无参数构造函数,存在super()对超类构造函数的默认调用。
  • 这就像类层次结构一样一直持续到Object类。

事实上,如果你不在超类中编写无参数构造函数,那么子类声明将引发编译器错误。

public class Super {

    public Super(int num){

    }
}

public class Sub extends Super {

}

在这里,类Sub将不会编译给出错误Implicit super constructor Super() is undefined for default constructor,因为它在超类中找不到无参数构造函数,因为default no-argument constructor编译器提供的 ie 将隐式调用super().

  • 仅当没有定义其他构造函数时,编译器才提供默认的无参数构造函数
  • 正如我们已经明确定义的那样Super(int num),我们将必须明确创建无参数构造函数,如下所示。

      public Super(){
    
    }
    
于 2013-07-05T10:00:23.957 回答
1

首先,您不必创建父实例 ( Parent) 来实例化子类 ( Employee)。你一定理解错了。

调用父类的构造函数并不意味着创建一个新的父实例对象(您没有使用 调用它new,因此不会创建新实例)。您正在创建一个子实例,为此,由于继承,您需要首先调用父级的构造函数。例如,想象一下父类具有private必须在构造函数中初始化的字段(例如private final字段)。该字段不能从子类访问,但可以从父类构造函数初始化。您需要在子实例中初始化此字段,唯一的方法是调用super().

在这种情况下Person,默认情况下会调用一个默认构造函数,无需显式调用它。

但如果Person没有默认构造函数,则需要显式调用它。例如:

public class Person{
    private final String name;
    public Person(final String name) {
        this.name = name;
    }
}

public class Employee extends Person {
   public Employee() {
   }
}

这不会编译。您需要进行修改Employee,使其显式调用Person构造函数。例如:

public class Employee extends Person {
   public Employee(final String name) {
      super(name);
   }
}
于 2013-07-05T10:06:48.980 回答
1

每当您实例化一个子类时,它都会首先调用您的超类的构造函数。

您可以在此处找到更多相关信息:JSL §8.8.7

人.java

public class Person {
    public Person() {
        System.out.println("Super class constructor called");
    }
}

雇员.java

public class Employee extends Person {
    public Employee() {
        System.out.println("Sub class constructor called");
    }
}

如果您随后实例化您的员工:

Employee e = new Employee();

输出:

超类构造函数调用

子类构造函数调用

于 2013-07-05T10:07:06.390 回答
0

超类的 nullary 构造函数被隐式调用。

于 2013-07-05T10:00:58.183 回答
0

这是因为构造函数链接:

默认情况下,任何构造函数中的第一条语句是super();(这是对超类默认构造函数的调用)。

我没有创建 Person 实例,但它是合法的:那是因为您在 Person 类中有一个默认构造函数。所以Employee类构造函数实际上可以调用超类构造函数。人()

最重要的是,您要在其中声明构造函数的当前类,直到基类的所有构造函数都应该可以通过 super() 访问。如果没有,您必须通过使用适当参数的 super 显式调用来显式地使它们可访问。

于 2013-07-05T10:02:40.770 回答
0

您遇到了 java 的一个奇怪之处。

如果您没有定义任何构造函数、默认值或“无参数”,则构造函数是隐式定义的。这就像看不见的代码。

如果您定义任何构造函数,args 或没有 args,隐式默认构造函数就会消失。

更复杂的是,任何子类构造函数的第一行必须是调用超类的构造函数。如果您没有显式调用一个,则隐式调用无参数构造函数。

于 2013-07-05T10:44:57.843 回答