9

我的老师给了我一个问题:

“在 Java 中创建对象时会发生什么”。

据我所知,内存分配、变量初始化和构造函数方法调用发生在创建对象时。

但我的老师说我几乎是对的。后面的 2 件事都是对的,除了内存堆。相反,他说内存分配发生了。我认为该对象存储在堆中,所以我的老师错了。你认为是吗?

4

5 回答 5

13

与往常一样,为这类问题找到解决方案的最佳位置是在 Java 语言规范中。

具体来说,从新建实例部分可以理解为,这是新建对象时的顺序,只要不出现异常即可:

  1. 内存已分配。
  2. 字段被初始化为其默认值
  3. 调用所选构造函数的“第一行”,除非它是Object. 第一行是指对or的显式调用,或对 的隐式调用super()this()super()
  4. 执行实例初始化程序并将字段初始化为其请求的值(实际上,字段初始化通常编译为实例初始化程序的内联部分)。
  5. 其余的构造函数代码被执行。

现在,您的老师有可能将内存分配作为实际的操作系统调用来讨论 - 在这种情况下,他是正确的,因为 JVM 管理自己的堆,因此 Java 内存分配不一定会转换为操作系统内存分配调用(尽管可能)。

于 2013-06-12T06:09:59.330 回答
3

我会用一个简单的例子来回答这个问题。

假设你有一堂课Car。现在你写:

Car car;
car = new Car();

第一条语句在堆栈中创建一个引用car

在第二条语句中,Car类将被加载到主内存中,然后它将为Car堆中的成员分配内存。发生这种情况时,成员将使用 JVM 提供的值进行初始化。

于 2013-06-12T06:03:24.863 回答
2

除了其他人所说的之外,如果这是对象的第一次使用,那么它的类必须被初始化 - 如JLS中所述(关于新实例创建的部分之前的部分!)。

这基本上涉及将有关类的必要信息加载到内存中,即为Klass静态变量和方法表创建一个对象。这也可能涉及加载超类和接口。这一切都是由ClassLoader.

于 2013-06-12T09:57:25.760 回答
2

当 JVM 运行程序时,每当创建一个新对象时,JVM 都会为该对象保留作为堆的一部分(该对象将存储在其中)。保留的堆数量取决于对象的大小。

JVM 在堆中映射出这个段来表示正在存储的对象的所有属性。对对象的引用(堆中的地址)由 JVM 保存并存储在允许 JVM 跟踪已在堆上分配的所有对象的表中。JVM 稍后使用这些引用来访问对象(当程序访问对象时)。

于 2013-06-12T06:08:31.543 回答
2

当在java中创建对象时,这6个步骤将一一发生--- 1.JVM为引用变量分配8个字节的内存并将默认值分配为null。

  1. JVM会验证类加载是否完成,如果类已经加载则忽略,否则执行类加载。
  2. 在类加载时,如果有任何静态变量,那么它将分配内存。
  3. 通过使用 new 运算符,将在堆内存中创建对象内存。
  4. 在创建对象时,如果有任何实例变量,那么这些变量将在对象内存中分配内存。
  5. 它将对象内存地址分配给首先创建的引用变量。
于 2018-08-13T11:52:54.230 回答