创建子类的实例是否会自动运行超类的构造函数?

时间:2015-12-06 05:33:42

标签: java oop inheritance

我们说我有这些课程:

public class Animal {

  static int counter = 0;

  public Animal() {
    counter += 1;
    System.out.println("Animals counter is currently " + counter);
}



public class Cat extends Animal {

  static int counter1 = 0;

  public Cat() {
    counter1 += 1;
    System.out.println("Cats counter is currently " + counter1);
}



public class Main {

  public static void main(String[] args) {
    Cat Cat1 = new Cat();
    Animal Animal1 = new Animal();
    Cat Cat2 = new Cat();
  }
}

当我运行Main时,我得到以下输出:

Animals counter is currently 1
Cats counter is currently 1
Animals counter is currently 2
Animals counter is currently 3
Cats counter is currently 2

因此,每当我创建Cat的实例时,它也会增加Animal计数器。我想澄清为什么会这样。显然,每次我创建一个Cat时,Animal的构造函数都在运行,但为什么呢?

2 个答案:

答案 0 :(得分:3)

从另一个类继承时,必须在构造函数中首先调用super()。如果没有,编译器将插入该调用。这就是在创建Sub对象时也调用超级构造函数的原因。

这不会创建两个对象,只有一个Sub对象。调用超级构造函数的原因是,如果超类可以拥有需要由其构造函数初始化的私有字段。

编译器插入超级构造函数后,子类构造函数如下所示:

public Cat() {
    super(); //implicit call
    counter1 += 1;
    System.out.println("Cats counter is currently " + counter1);
}

注意: - 如果你有参数化的构造函数而你没有写super(),你将收到编译错误。你必须明确提到你要传递的参数。

编辑: -

Java doc中关于java的静态的简要概述,其中静态数据成员与类相关联,而不是与任何类相关联 对象

  

有时,您希望拥有所有对象共有的变量。   这是通过静态修改器完成的。有的领域   声明中的static修饰符称为静态字段或类   变量。他们与班级有关,而不是与班级有关   宾语。该类的每个实例都共享一个类变量,即   在内存中的一个固定位置。任何对象都可以更改a的值   类变量,但类变量也可以在没有的情况下进行操作   创建一个类的实例。

答案 1 :(得分:2)

  

显然,每次创建Cat时,Animal的构造函数都在运行,但为什么呢?

因为CatAnimal类的子类,所以在创建子类的实例时,默认情况下会调用超类的默认构造函数。

在内部,这是这样的:

public Cat() {
  super(); // call to Animal class constructor.
  counter1 += 1;
  System.out.println("Cats counter is currently " + counter1);
}

继承代表is-a关系,CatAnimal

当前static int counter = 0; counter变量被声明为静态,这意味着它将属于该类而不属于该类的实例。所以该类的所有实例都将共享counter变量。这就是为什么counter在创建子类和超类的实例时不断增加的原因。

当你创建non-static时,它将作为实例成员包含在类的状态中。这意味着,每次调用超类Animal构造函数时,其值都会递增为1(默认值为0,您也已经提到过),可以直接或直接通过子类构造函数。