伟大的问题。你正在探索的是Java如何初始化对象 – 并且涉及到许多步骤。
i know is constructor is also a method (Maybe i am wrong).
几乎正确。构造函数是一种特殊的方法。如果反编译类文件,您将看到构造函数重命名为< init> ;. < init>与其他方法的处理不同,例如,除非通过使用关键字new或super,否则不能被明确调用。这是根本的,它是在JVM本身实现的,而不是在Java语言中定义的东西。
How many number of Object is created in this case.
创建一个对象–C的实例。
C另外且同时是B的实例以及A和Object的实例。
If one object is created then how internally super() is calling Parent class Constructor . How Super is able to call parent class constructor.
这是我们进入初始化 – 初始化是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()作为构造函数的第一行。这意味着构造函数按顺序严格执行:
>对象
> 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。
总之,只有一个对象,它是在一个数字的阶段创建和初始化。在这些阶段期间,根据定义,对象未被完全定义。