实例化

标签 java oop jvm

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

我理解通常为了让您正确使用这些东西而给出的抽象解释,但 JVM 是如何真正做到这一点的。

最佳答案

当一个对象被实例化时,实际上只有非静态数据被“创建”,以及对创建它的对象类型的引用。

没有任何方法被复制。

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

那样的话,如果您有一个对另一个方法的顶级调用,但另一个方法已被覆盖,那么将调用被覆盖的方法,因为这是表中指针指向的位置。由于这种机制,调用重写方法的时间不会比调用顶级方法多。

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

变量问题与完全不同的机制“ namespace ”有关。变量根本不是“子类化”的(它们不进入调度表),但是公共(public)或 protected 变量可以被局部变量隐藏。这都是编译器在编译时完成的,与你的运行时对象实例无关。编译器确定您真正需要的对象并将对该对象的引用填充到您的代码中。

范围规则通常有利于“最近”变量。任何具有相同名称的更远的东西都将被忽略(阴影)以支持更接近的定义。

如果您有兴趣,可以更具体地了解内存分配:所有“对象”都分配在“堆”上(实际上比真正的堆更高效、更漂亮,但概念相同。)变量始终是指针--Java 永远不会复制一个对象,你总是复制一个指向那个对象的指针。方法参数和局部变量的变量指针分配是在栈上完成的,但是即使变量(指针)是在栈上创建的,它们指向的对象仍然不会在栈上分配。

我很想写一个例子,但这已经太长了。如果您想让我输入几个具有扩展关系的类,以及它们的方法和数据如何影响生成的代码,我可以……尽管问。

关于实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/220133/

相关文章:

java - Apache Camel BindException : "Can' t Assign Requested Address"

java - Spring Solr 存储库

oop - 恢复域对象的最佳方式

java - 在 JAR 中指定 JVM 堆大小

java - JVM -XX :MaxRAM option can be correctly used? 如何

java - 当我尝试在 net-beans 中运行它时,我收到 "java.lang.reflect.InvocationTargetException"。为什么会发生这种情况?

java - 正则表达式 - 如果一个字符后跟另一个字符,则只选择一个字符

java - 更改 List<String> 的自定义适配器

Java - 从单独的组件中重绘组件

java - 在java中的方法中的特定索引处使用数组