我之前问过这个问题,把事情搞清楚了。 但是,我有一些疑问,解释如下:
让我们假设需要有一个包含 100 个元素的数组:
1) 声明数组:
Integer[] intArr;
2) 为 100 个整数元素分配内存,并将引用分配给变量
intArr = new Integer[100];
现在真正的疑问来了。
哪一种是为数组中的各个元素赋值的正确方法:
方法1:
intArr[1] = 1;
方法2:
intArr[1] = new Integer(1);
我的怀疑是我们已经为 100 个元素分配了内存,如果我们使用 方法 2 ,我们不是再创建一个内存区域并将它们分配给 intArr1 吗?
intArr[index] 是否保存引用的地址,或者实际对象是否可以放置在 intArr[index] 中。
希望能得到一些见解来消除这个疑问。
这两行在某种程度上是等价的。第一种使用自动装箱。它实际上直接等同于:
intArr[1] = Integer.valueOf(1);
不同之处在于,这可以多次重用对同一Integer
对象的引用,而在第二种方法中,您正在创建新的Integer
对象。您可以在此处看到差异:
intArr[1] = Integer.valueOf(1);
intArr[2] = Integer.valueOf(1);
System.out.println(intArr[1] == intArr[2]); // True, references to the same object
intArr[1] = new Integer(1);
intArr[2] = new Integer(1);
System.out.println(intArr[1] == intArr[2]); // False, references to the different objects
在所有情况下,数组的值都是引用。它们从来都不是对象本身。当您分配数组时,这将为 100 个引用创建足够的空间,并且这些引用最初都是null
的。
如果你想要一个直接包含整数数据的数组,只需使用int[]
而不是Integer[]
。
我的怀疑是我们已经为 100 个元素分配了内存,如果我们使用 方法 2 ,我们不是再创建一个内存区域并将它们分配给 intArr1 吗?
您在new Integer[100]
中分配的内存用于数组将包含的 100 个对象引用,而不是它包含的对象。添加到数组时,由于它是对象数组,因此您仍然必须创建对象。
您的方法实际上本质上是相同的,因为编译器将通过Integer.valueOf(1)
自动"框"方法1中的1
,更改:
intArr[1] = 1;
自
intArr[1] = Integer.valueOf(1);
(即使不依赖于自动装箱,Integer.valueOf
通常是获取Integer
实例的更好方法,因为它可以缓存它们 [并且始终缓存 -128 到 127 的实例]。
让我们继续一些ASCII艺术:
当您执行以下操作时:
Integer[] intArr;
你的记忆中有这样的东西:
intArr[null]
例如,一个包含null
的变量。现在,您为数组分配内存并将其分配给变量:
intArr = new Integer[100];
你会得到这样的东西:
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−intArr[Ref21345]−−−−>| 整数[100] | +−−−−−−−−−−−−−−−−+ | 0:空 | | 1:空 | |... | |99:空 | +−−−−
−−−−−−−−−−−−+现在我们有空间存储 100 个对象引用;它们都是从null
开始的。然后你做:
intArr[0] = 1;
编译器变成
intArr[0] = Integer.valueOf(1);
你会得到:
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−intArr[Ref21345]−−−−>| 整数[100] | +−−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | 0: [ref84651] |−−−−>|整数 | | 1:空 | +−−−−−−−−−−+ |... | |值:1 | |99:空 | +−−−−−−−−−−+ +−−
只是为了详细说明。
如果你说
int[] vals = new int[10];
您正在为 10 个整数分配空间。这意味着此处分配的内存为10* 32
位。
Integer[] vals = new Integer[10].
此处分配的内存什么都没有(除了数组对象本身)。数组中的所有元素都是空的,并且不会携带任何内存。
所以当你这样做时
intArr[1] = new Integer(1);
为new Integer(1)
分配的内存和对intArr
索引的引用,因此您实际上只分配一次内存。
即使你正在做
intArr[1] = 1;
它实际上自动装箱以Integer
并存储该引用。