假设我的类中有一个整数数组:
public class Foo {
private Integer[] arr = new Integer[20];
.....
}
在 64 位架构上,此空间要求为 ~ (20*8+24) + 24*20 {引用所需的空间 + 一些数组开销 + 对象所需的空间}。
为什么 java 存储对所有 20 个 Integer 对象的引用?不知道第一个内存位置和数组中的项数是否足够? (假设我也在某处读到数组中的对象无论如何都是连续放置的)。我想知道这种实现的原因。对不起,如果这是一个笨拙的问题。
最佳答案
与所有其他类
一样,Integer
是引用类型。这意味着它只能通过引用间接访问。您不能在字段、局部变量、集合中的插槽等中存储引用类型的实例——您始终必须存储引用并单独分配对象本身。这有多种原因:
- 您需要能够表示
null
。 - 您需要能够用 子类型 的另一个实例替换它(假设子类型是可能的,即该类不是
final
)。例如,Object[]
实际上可以存储任意数量的不同类的实例,这些类的大小差异很大。 - 您需要保留共享,例如
a[0] = a[1] = someObject;
所有三个 之后必须引用相同 对象。如果对象是可变的,这一点就更为重要(甚至至关重要),但即使是不可变对象(immutable对象),也可以通过引用相等性检查 (==
) 观察到差异。 - 您需要原子的引用分配(参见 Java 内存模型),因此复制整个实例比看起来更昂贵。
由于这些和许多其他限制,始终存储引用是唯一可行的实现策略(通常)。在非常特殊的情况下,JIT 编译器可能会避免完全分配一个对象并直接存储它(例如在堆栈上),但这是一个模糊的实现细节,并不广泛适用。我只是为了完整性而提及这一点,因为它是对假设规则的精彩说明。
关于Java 对象数组内存要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15550611/