Java实例化

  1. 当一个对象在Java中实例化时,真正进入内存的是什么?
  2. 是否包含父母构造函数的副本?
  3. 为什么隐藏数据成员在转换时的行为与重写方法不同?

我理解通常用于正确使用这些东西的抽象解释,但JVM是如何做到的。

实例化对象时,只有非静态数据实际上是“已创建”,并且引用了创建它的对象类型。

没有任何方法被复制。

创建它的类的“引用”实际上是一个指针分派表。 每个可用于该类的方法都有一个指针。 指针始终指向该方法的“正确”(通常是对象树中最低/最具体的)实现。

这样,如果您对另一个方法进行了顶级调用,但另一个方法已被覆盖,则将调用重写的方法,因为这是表中指针指向的位置。 由于这种机制,调用重写方法不应该花费更多时间而不是顶级方法。

指针表+成员变量是类的“实例”。

变量问题与完全不同的机制“名称空间”有关。 变量根本不是“Subclassed”(它们不会进入调度表),但公共或受保护的变量可以被局部变量隐藏。 这完全由编译器在编译时完成,与运行时对象实例无关。 编译器确定您真正想要的对象,并将对它的引用填入您的代码中。

范围规则通常倾向于“最近”变量。 任何远离同名的东西都会被忽略(阴影),以支持更接近的定义。

如果您感兴趣,可以更详细地了解内存分配:所有“OBJECTS”都分配在“Heap”上(实际上比真正的堆更高效和美观,但是相同的概念。)变量总是指针 – Java永远不会复制对象,你总是复制指向该对象的指针。 方法参数和局部变量的变量指针分配在堆栈上完成,但即使在堆栈上创建变量(指针),它们指向的对象仍然永远不会在堆栈上分配。

我很想写一个例子,但这已经太久了。 如果你想让我输出一些带有扩展关系的类,以及他们的方法和数据如何影响生成的代码,我可以……只是问。

我想你会发现这是一个全面的例子:

http://www.onjava.com/pub/a/onjava/2005/01/26/classloading.html

  1. 内存是从堆中分配的,用于保存对象及其超类的所有实例变量和特定于实现的数据。 特定于实现的数据包括指向类和方法数据的指针。

  2. 对象的实例变量初始化为其默认值。

  3. 调用派生程度最大的类的构造函数。 构造函数做的第一件事是调用构造函数的大写。这个过程一直持续到调用java.lang.Object的构造函数为止,因为java.lang.Object是java中所有对象的基类。

  4. 在执行构造函数体之前,将执行所有实例变量初始值设定项和初始化块。 然后执行构造函数的主体。 因此,基类的构造函数首先完成,最派生类的构造函数最后完成。