在Java中创建对象时会发生什么?

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

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

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

但我的老师说我几乎是对的。 除了内存堆之外,后来的两件事情是正确的。 相反,他说内存分配发生了。 我认为该对象存储在堆中,所以我的老师错了。 你这么认为吗?

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

具体来说, 从新实例创建一节可以理解,只要没有exception发生,这就是创建新对象时的顺序:

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

现在,您的老师可能正在将内存分配视为实际的操作系统调用 – 在这种情况下,他是正确的,因为JVM管理自己的堆,因此Java内存分配不一定转换为OS内存分配呼叫(虽然可能)。

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

说你有Car 。 现在你写:

 Car car; car = new Car(); 

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

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

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

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

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

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

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

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