【问题标题】:Does creating an instance of a subclass automatically run the superclass's constructor?创建子类的实例会自动运行超类的构造函数吗?
【发布时间】:2015-12-06 05:33:42
【问题描述】:

假设我有这些课程:

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 的构造函数都会运行,但为什么呢?

【问题讨论】:

    标签: java oop inheritance


    【解决方案1】:

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

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

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

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

    注意:-如果你有参数化构造函数并且你不写super(),你会得到一个编译错误。您必须明确提及您传递的参数。

    编辑:-

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

    有时,您希望拥有所有对象共有的变量。 这是通过静态修饰符完成的。具有 声明中的静态修饰符称为静态字段或类 变量。它们与类相关联,而不是与任何 目的。类的每个实例共享一个类变量,即 在内存中的一个固定位置。任何对象都可以改变 a 的值 类变量,但类变量也可以在没有 创建类的实例。

    【讨论】:

    • 如果是这样,为什么如果我删除动物中计数器变量的静态限定符,我的输出会改变?无论如何不应该更新计数器吗?如果我从动物中的计数器中删除静态,这就是我得到的结果:动物计数器当前为 1 猫计数器当前为 1 动物计数器当前为 1 动物计数器当前为 1 猫计数器当前为 2(对不起格式)
    • @SakeebHossain 如果您的问题得到解决,请将答案标记为已接受。这样可以帮助其他寻找类似问题的人
    【解决方案2】:

    很明显,每次我创建猫时,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 在您创建子类和超类的实例时不断增加的原因。

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

    【讨论】:

    • 如果是这样,为什么如果我删除动物中计数器变量的静态限定符,我的输出会改变?它不应该更新计数器吗?如果我从动物中的计数器中删除静态,这就是我得到的结果:动物计数器当前为 1 猫计数器当前为 1 动物计数器当前为 1 动物计数器当前为 1 猫计数器当前为 2
    • @SakeebHossain 我已经更新了答案,请检查。
    猜你喜欢
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多