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

我明白为了让你正确使用这些东西而给出的抽象解释,但JVM是如何真正做到的。Java实例化

回答

17

当一个对象被实例化,只有非静态数据实际上是“创建”是,与该参考沿创建它的对象的类型。

没有任何方法被复制。

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

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

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

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

范围规则通常倾向于“最近的”变量。任何远离相同名称的东西都会被忽略(隐藏)以支持更接近的定义。如果你有兴趣,所有的“OBJECTS”都被分配到“堆”上(事实上它比真正的堆更有效率,更漂亮,但是同样的概念。)变量总是指针 - Java永远不会复制一个对象,你总是复制一个指向该对象的指针。方法参数和局部变量的变量指针分配在堆栈上完成,但即使在堆栈上创建了变量(指针),它们指向的对象仍然不会分配到堆栈上。

我很想写一个例子,但这已经太长了。如果你想让我用一个扩展关系来输入一些类,以及它们的方法和数据如何影响代码的生成,我可以......请问。

+0

你还愿意写一个例子吗?如果是的话,请这样做。 – Touchstone 2015-06-09 08:17:40

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

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

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

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

+0

所有这些都是一些有趣的信息,但我倾向于认为Bill未回答的部分也没有回答这个问题。 – chiccodoro 2014-08-25 10:19:28