好问题。您要探究的是Java如何 初始化对象 -涉及许多步骤。
我知道构造函数也是一种方法(也许我错了)。
几乎是正确的。构造函数是一种特殊的方法。如果您反编译一个类文件,则会看到构造函数被重命名为
<init>。
<init>与其他方法的处理方式不同,例如,除非通过使用关键字
newor,否则不能显式调用它
super。这是如此基础,以至于它是在JVM本身中实现的,而不是用Java语言定义的。
在这种情况下,将创建多少个对象。
创建了一个对象-的实例
C。
C是另外地和同时的一个实例
B和实例
A,并且还
Object。
如果创建了一个对象,则在内部如何
super()调用Parent类Constructor。Super如何调用父类的构造函数。
这是我们进行初始化的地方-初始化是JVM如何创建对象的新实例并设置所有成员值-特定类的成员值和超类的成员值。涉及几个阶段:
- 加载所有引用的类并初始化这些类。类初始化本身并不简单,因此在此不做介绍。值得一读。
- 分配的内存块用于保存实例的成员,其中包括的所有成员
A
,B
以及C
。 注意, 这解释了问题的一个方面:基类及其子类的构造函数如何更新或引用相同的对象- 所有类的实例的所有成员都一个接一个地存储在同一块内存中 。 - 将所有成员初始化为其 默认值 。例如,
int
和float
成员将设置为0和0.0f。 - 执行或计算成员初始化器,例如:
private int a = 10; private int b = a * 5; private String c = Singleton.getInstance().getValue();
- 注意(1)成员初始化严格按照在类中声明成员的顺序进行。这意味着声明后面对成员的引用已损坏:
private int a = b * 5; // Forward reference; won't compile private int b = 10;
- 注意(2)Java中有一个未充分使用的工具,可以 在 执行构造函数 之前 运行任意代码以初始化值。这些代码块现在再次严格按照声明的顺序执行:
private int a; private int b = 1; { // Initization occurs after b but before c. // c cannot be referenced here at all int i = SomeClass.getSomeStatic(); a = i * 2; } private int c = 99;执行的构造函数
C
。构造函数必须直接从超类调用构造函数,否则编译器将自动添加super()
为构造函数的第一行。这意味着构造函数严格按顺序执行:Object
A
B
C
现在,该对象已初始化并可以使用。如果使用实例方法初始化值,则可能会做一些危险的事情:
public class Wrong { int a = getB(); // Don't do this! int b = 10; public int getB() { return b; } }在这里,
a被初始化为
0。这是因为在
getB()调用该点时,Java已将值清除为
b默认值(
0),但尚未
10在初始化的第二阶段将其设置为。
总而言之-只有一个对象,并且它是分阶段创建和初始化的。在那些阶段中,根据定义,对象没有完全定义。



