Pra*_*eek 12 java inheritance object
基类:
public class Inheritance {
int i;
Inheritance() {
System.out.println("I am in base class" + i);
}
}
Run Code Online (Sandbox Code Playgroud)
派生类:
public class TestInheritance extends Inheritance {
TestInheritance() {
System.out.println("I am in derived class");
}
public static void main(String[] args) {
TestInheritance obj = new TestInheritance();
}
}
Run Code Online (Sandbox Code Playgroud)
这就是我对上面发生的事情的想法.
当我默认创建派生类的对象时,super()调用基类的构造函数并初始化变量i.
现在,我的问题是:在这种情况下,构造函数是否只初始化变量i而不创建类的具体对象?
从我到目前为止所读到的,只有一个对象被创建 - 派生类中有i变量.
但是从调用基类的构造函数和调用派生类的构造函数的时间点开始如何/在哪里i存储?
基类是抽象类的情况会怎样.
如果我能知道在不同时间点内存中会发生什么,我真的很感激.
如果我说了一些根本不正确的话,请告诉我.我真的想知道这件事是如何运作的.
在物理上你创造了一个物体,但在概念上你创造了2个。这就像一个女婴出生时:在物理上她只是一个,但在概念上一个新的女性诞生了,一个新的人类也诞生了,一个新的人类诞生了。新的众生已经诞生,地球上的新居民已经诞生,等等。是的,正是如此。这里也有继承关系(subTyping),我是故意的。为了避免混淆,最好说只有一个物体具有多个面;同时属于不同(超)类的一个对象。
现在,关于逻辑部分已经说得够多了,让我们检查一下物理部分。单个(物理)对象是在内存中使用以下结构创建的
+--------------------------+----------------------------+
| B | C' +
+--------------------------+----------------------------+
Run Code Online (Sandbox Code Playgroud)
第一部分 (B) 包含从 C 的超类 B 继承的所有字段(如果有)。第二部分(C',我用于'“补充”)包含 C“专有”的所有字段(即不是从 B 继承而是在 C 本身中定义)。需要注意的是,创建的对象不是从 C' 开始,而是从 B 开始。继承字段与新字段的组合构成了完整的对象。
现在,如果 B 有自己的超类 A,那么结构将如下所示:
+--------+-----------------+----------------------------+
| A | B' | C' +
+--------+-----------------+----------------------------+
Run Code Online (Sandbox Code Playgroud)
这里需要注意的是B == A + B'。换句话说,C 不需要了解 A。它只关心它的直接超类 B,而 B 隐藏了它的内部结构。
回答具体问题:
在这种情况下,构造函数是否只初始化变量 i 而没有创建类的具体对象?
与上面的 A、B 和 C 在结构上链接一样,它们在初始化期间也是链接的。如果不是这样,就好像我原来的例子中的女孩出生时就没有任何其他我们所知道的东西,她也被定义为。不可能。完全矛盾。因此,两个类的构造过程都被执行,其中包括:将字段初始化为“零”值(null对于引用和falsefor boolean's),并执行一个构造函数(可以调用其他构造函数)。
在这种特殊情况下,字段i被初始化,Inheritance构造函数被执行,TestInheritance的字段(如果有的话)将被初始化,然后 aTestInheritance的构造函数将被执行。我们怎样才能准确地知道每个类的构造函数是什么?比较简单。引发一切的是new TestInheritance()。这显然表明 的TestInheritance构造函数没有任何参数(该参数存在;否则会出现编译错误)。但是,此构造函数没有显式调用超类的任何构造函数(通过关键字super(...))。正如我们在上面看到的,这是不可能的,编译器会自动插入与 等价的内容super(),即不带参数调用超类的构造函数 ( Inheritance())。同样,这个构造函数存在,一切都很好。输出将是:
I am in base class 0
I am in derived class
Run Code Online (Sandbox Code Playgroud)
没有参数的构造函数被称为“默认构造函数”,主要有 3 个原因: - 它们通常非常简单,因为它们没有参数。- 当子类的构造函数没有显式调用任何超类构造函数时,它们会被自动调用。- 它们是自动为那些类提供的,无需程序员显式编写任何构造函数。在这种情况下,构造函数不执行任何操作,仅进行初始化。
从我到目前为止所读到的内容来看,只创建了一个对象 - 派生类的对象,其中包含 i 变量。
这并不完全正确。从物理上来说,确实只创建了一个对象,但它对应于new( TestInheritance) 所使用的类,在本例中该类恰好没有字段,但这无关紧要。事实上,两条输出行都被打印。从概念上讲……我们已经提到过这一点。
但是从调用基类的构造函数到调用派生类的构造函数的时间点,i 是如何/在哪里存储在内存中的?
当执行时,在调用构造函数之前,甚至在执行初始化之前,发生的第一件事是为整个对象new TestInheritance()分配内存。- 通常这个内存是“脏的”,这就是它需要初始化的原因。- 's 字段、其超类' 字段等都有空间。甚至内存中对象内每个字段的位置也是预先知道的。TestInheritance
因此,即使在调用基类的构造函数之前,也已经为i任何其他字段分配了内存,只是它们是“脏的”(未初始化)。
基类是抽象类的情况会怎样?
没有区别。唯一的问题是你不能自己创建抽象类的对象。您将它们创建为(具体)子类的一部分。这类似于一个新的人类不能由他/她自己诞生。要么是女婴,要么是男婴。
如果我能知道不同时间点记忆中发生了什么,我将非常感激。
我希望我做到了。
如果我说了一些根本不正确的话,请告诉我。我真的很想知道这东西是如何运作的。
没有什么“根本上不正确”。