不要在子类的构造函数中创建超类实例,但完全合法

时间:2013-07-05 09:58:52

标签: java oop constructor constructor-overloading

我在scjp指南中读到如下

  

事实上,你不能在不调用的情况下创建一个新对象   对象的实际类类型的构造函数,也是   每个超类的构造函数!

例如

public class Person{

}

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

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

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

6 个答案:

答案 0 :(得分:1)

他们实际上的意思是

  • 当你创建一个子类对象,即它的构造函数被调用时,那么超类构造函数会被调用internall
  • 这是因为对于默认的无参构造函数,存在对超类构造函数的默认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将具有隐式调用到super()

  • 只有在没有其他构造函数定义
  • 的情况下,编译器才会提供默认的无参数构造函数
  • 由于我们明确定义了Super(int num),我们必须如下所示明确地创建no-arg构造函数。

      public Super(){
    
    }
    

答案 1 :(得分: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);
   }
}

答案 2 :(得分:1)

无论何时实例化一个子类,它都会首先调用你的超类构造函数。

您可以在此处找到有关此内容的更多信息:JSL §8.8.7

<强> Person.java

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

<强> Employee.java

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

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

Employee e = new Employee();

<强>输出:

  

名为

的超类构造函数      

子类构造函数名为

答案 3 :(得分:0)

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

答案 4 :(得分:0)

因为构造函数链接:

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

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

底线,您声明构造函数的当前类,所有构造函数都可以通过super()访问基类的所有构造函数。如果没有,您必须通过使用适当的参数显式地通过super进行调用来明确地使它们可访问。

答案 5 :(得分:0)

你遇到了一个奇怪的java。

如果您没有定义任何构造函数,则默认情况下,或者&#34; no args&#34;,构造函数是隐式定义的。它就像隐形代码。

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

为了进一步理解这个谜团,任何子类构造函数的第一行必须是调用超类的构造函数。如果你没有明确地调用一个,那么no-args构造函数将被隐式地调用。