java - 继承和对象创建

标签 java object inheritance

基类:

public class Inheritance {
    int i;
    Inheritance() {
        System.out.println("I am in base class" + i);
    }
}

派生类:
public class TestInheritance extends Inheritance {

    TestInheritance() {
        System.out.println("I am in derived class");
    }

    public static void main(String[] args) {
        TestInheritance obj = new TestInheritance();        
    }
}

这就是我对上面发生的事情的看法。

当我默认创建派生类的对象时 super()被调用并调用基类的构造函数并初始化变量 i .

现在,我的问题是:在这种情况下,构造函数是否只初始化变量 i并且不创建类的具体对象?

从我到目前为止所读到的内容来看,只创建了一个对象 - 具有 i 的派生类的对象。其中的变量。

但是从基类的构造函数被调用到派生类的构造函数被调用的时间点是如何/在哪里i存储在内存中?

基类是抽象类会是什么情况。

如果我能知道在不同时间点内存中会发生什么,我将不胜感激。

如果我说了一些根本不正确的话,请告诉我。我真的很想知道这个东西是如何工作的。

最佳答案

物理上你创造了一个单一的物体,但概念上你创造了 2。就像一个女婴出生时: body 上她只是一个,但概念上已经诞生了一个新的女性,也诞生了一个新的人类,一个新的众生诞生了,地球上的新居民诞生了,等等。是的,正是如此。这里也有继承(subTyping)的关系,我是故意的。为避免混淆,最好说只有一个对象具有多个方面;一个对象同时是不同(超)类的成员。

现在,关于逻辑部分已经说得够多了,让我们来看看物理部分。单个(物理)对象在内存中使用以下结构创建

+--------------------------+----------------------------+
|             B            |              C'            +
+--------------------------+----------------------------+

第一部分 (B) 包含从 C 的父类(super class) B 继承的所有字段(如果有)。第二部分(C',我使用 ' 作为“补码”)包含所有 C 的“专有”字段(即不是从 B 继承的,而是在 C 本身中定义的)。需要注意的是,创建的对象不是从 C' 开始,而是从 B 开始。正是继承字段与新字段的组合构成了完整的对象。

现在,如果 B 有自己的父类(super class) A,结构将是这样的:
+--------+-----------------+----------------------------+
|    A   |      B'         |              C'            +
+--------+-----------------+----------------------------+

这里需要注意的是 B == A + B' 。换句话说,C 不需要知道 A。它只关心它的直接父类(super class) B,它隐藏了它的内部结构。

回答具体问题:

Does the constructor in this case only initialize the variable i and doesn't create a concrete object of class?



与上面的 A、B 和 C 在结构上链接的方式相同,它们也在初始化期间链接。如果不是这样,就像我最初的例子中的女孩出生时没有任何其他东西我们 知道 根据定义 她也是 。不可能。完全的矛盾。因此, 类的构造过程都进行了,其中包括:将字段初始化为“零”值(null 用于引用,false 用于 boolean 的构造函数),并执行一个可以调用其他构造函数的构造函数。

在这种特殊情况下,初始化字段 i,执行 Inheritance 构造函数,初始化 TestInheritance 的字段(如果有的话),然后执行 TestInheritance 的构造函数。我们如何才能准确地说出每个类的构造函数?比较简单。启动一切的是 new TestInheritance() 。这显然表明 TestInheritance 的构造函数没有任何参数(存在;否则会出现编译错误)。但是,此构造函数并未显式调用父类(super class)的任何构造函数(通过关键字 super(...) )。正如我们在上面看到的,这是不可能的,编译器会自动插入等效于 super() 的值,即对父类(super class)的构造函数的调用,没有参数( Inheritance() )。同样,这个构造函数存在,一切都很好。输出本来是:
I am in base class 0
I am in derived class

没有参数的构造函数被称为“默认构造函数”主要有以下三个原因:
- 它们通常非常简单,因为它们没有参数。
- 当子类的构造函数没有显式调用任何父类(super class)构造函数时,它们会被自动调用。
- 它们是为那些类自动提供的,而无需程序员显式编写任何构造函数。在这种情况下,构造函数什么都不做,只进行初始化。

From what I have read so far there is only one object created - of the derived class which has i variable in it.



这并不完全正确。从物理上讲,确实只创建了一个对象,但它对应于与 new ( TestInheritance ) 一起使用的类,在这种情况下,它恰好没有字段,但这无关紧要。事实上,两个输出行都被打印出来了。从概念上讲……我们已经提到了这一点。

But from the time the constructor of base class is called and the point in time where constructor of the derived class is called how/where is i stored in memory?



当执行 new TestInheritance() 时,在调用构造函数之前,甚至在执行初始化之前,发生的第一件事就是为 整个对象 分配内存。
- 通常这个内存是“脏的”,这就是它需要初始化的原因。
- TestInheritance 的字段、其父类(super class)的字段等有空间。甚至每个字段在内存中的对象内的位置也是预先知道的。

因此,即使在调用基类的构造函数之前,已经为 i 和任何其他字段分配了内存,只是它们是“脏的”(未初始化)。

And what would be the case in which base class is an abstract one.



没有区别。唯一的一个是你不能自己创建抽象类的对象。您将它们创建为(具体)子类的一部分。这类似于一个新的人类不能由他/她自己出生的事实。它要么是一个女婴,要么是一个男婴。

I would really appreciate if I can know what happens in memory at different points of time.



我希望我做到了。

If I have said something which is fundamentally incorrect please let me know. I really want to know how this thing works.



没有什么“根本不正确”。

关于java - 继承和对象创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18391844/

相关文章:

java - 针对不同版本的 JRE

java - "Cannot locate configuration source"在 Tomcat 中使用 commons-configuration XMLConfiguration

java - 高级 for-each header (对于元素 : method_returning_array())?)内的方法调用的任何已知负面影响

java - 我试图将歌曲的名称和艺术家的名称分开

php - PHP 问题中的简单对象 [新手]

swift - 快速在标签中显示数组

c# - 从基类引发事件

objective-c - 使用自定义方法将自定义对象添加到数组 Swift 问题

c# - Entity Framework 继承

javascript - 对 JavaScript 原型(prototype)继承感到困惑