【问题标题】:Java Wrapper & Primitive Memory AllocationJava 包装器和原始内存分配
【发布时间】:2016-04-16 06:25:20
【问题描述】:

我在面试中被问到以下问题

考虑以下代码

int i =0
Integer e1 = 0
它们将在哪个内存中创建?

据我了解

对于int i =0

原始数据类型进入堆栈内存并

对于Integer e1 = 0

作为包装类的整数进入堆内存

请帮助正确理解?

【问题讨论】:

  • 是的,您的理解是正确的。但是 JLS 允许将 -128 到 127 范围内的整数作为静态实例存储在 Integer 类中。
  • 对于像e1这样的局部引用变量,引用本身将在堆栈上,但它所引用的对象将在堆上。

标签: java memory-management


【解决方案1】:

比这要复杂一些。

首先,您需要知道iei 变量是对象的局部变量还是字段(静态或实例)1

如果它们是局部变量:

  • i 在堆栈上。
  • ei 在堆栈上(一个引用),它引用堆中的一个对象。

如果它们是实例或类的字段:

  • i 在堆上(作为实例或类的一部分)。
  • ei 在堆上(作为实例或类的一部分),它引用堆中的一个对象。

最后,值得注意的是Integer e1 = 0 可能根本不会分配新的Integer 对象。存储在e1 中的引用可能是对已经存在的对象的引用。


1 - 还有另一种情况。如果iei 是内部类声明引用的局部变量,则在实例化内部类时将进行第二次复制。对于该副本,空间使用将如同 i / ei 是内部类的字段。

【讨论】:

    【解决方案2】:

    这是一个非常有趣的问题。

    使用原语,分配将在堆栈中,并将花费其所需的 4 个字节进行舍入或取整。

    但是当谈到包装器时,事情真的开始增长了。 如果我们将其与 C++ 相比,4 个字节将在堆中分配,这使得 e1 成为一个指针。

    假设我们使用的是 64 位机器,e1 将占用堆栈中的 8 个字节(+舍入)。

    并且堆数据块至少有一个小的 4-8bytes 头。

    查看这些类型的实现,我看不到每个实例使用的内存更多,因为所有辅助成员和常量都是静态的,因此所有实例都将使用用于此类型的“数据段”中的相同数据块.

    因此,添加所有这些表明包装器的分配将始终大于原语。 例如 - 通过极其粗略的计算,您会得到如下结果:

    基元:int -> 4 字节,包装器:整数 -> 8(stack) + 4 + 4 = 16 字节

    至于性能,看起来原语的操作速度比包装器快,但这是另一个讨论。

    希望这些信息有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多