我们说我有这些课程:
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的构造函数都在运行,但为什么呢?
答案 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的构造函数都在运行,但为什么呢?
因为Cat
是Animal
类的子类,所以在创建子类的实例时,默认情况下会调用超类的默认构造函数。
在内部,这是这样的:
public Cat() {
super(); // call to Animal class constructor.
counter1 += 1;
System.out.println("Cats counter is currently " + counter1);
}
继承代表is-a
关系,Cat
是Animal
。
当前static int counter = 0;
counter
变量被声明为静态,这意味着它将属于该类而不属于该类的实例。所以该类的所有实例都将共享counter
变量。这就是为什么counter
在创建子类和超类的实例时不断增加的原因。
当你创建non-static
时,它将作为实例成员包含在类的状态中。这意味着,每次调用超类Animal
构造函数时,其值都会递增为1(默认值为0,您也已经提到过),可以直接或直接通过子类构造函数。