我想知道Java的运行时如何知道对象的位置。为什么这段代码有效:
A类
class A{
int id;
A(int i){
id = i;
}
}
主要
ArrayList<A> array = new ArrayList<>();
for(int i=0; i<10; i++){
array.add(new A(i));
}
A fifth = array.get(5); // this object will be reallocated soon
for(int i=10; i<1000000; i++){
array.add(new A(i));
}
System.out.println("it's still alive " + fifth.id); // works, but why?
变量名称究竟与实际对象绑定的是什么?这是在运行时管理的吗?
编辑:我只是自己弄清楚了答案,因为ArrayList
下面的数组包含指向对象的指针,但这些对象本身一直都在同一个地点。只有指针数组移动。我整个晚上都在做C ++,而我的思绪一直在考虑包含非堆元素的向量。这就是为什么我混淆了这一点。
答案 0 :(得分:3)
您混淆的原因是您认为ArrayList
存储对象 - 但它不存在,它只存储引用(&#34;指针&#34; )对这些对象。因此,当内部数组扩展/重新分配时,对象仍然在同一个地方。
让我们来看看你的例子:
array
的起始数组位于100
i=5
new A(i)
在特定位置创建了A
,请说123
。然后array
数组的fith条目为A@123
fifth = array.get(5)
只需复制引用,因此fith
包含A@123
array
必须增长其数组时,它会创建一个新数组,例如在200
。然后,它会将所有现有条目复制到新位置,包括位置5的A@123
123
,因此A@123
中包含的引用fith
仍然有效对象只会在垃圾收集过程中被移动,但这在iavanish的回答中有所涉及。
答案 1 :(得分:2)
我已经进一步注释了您的源代码。 :)
ArrayList<A> array = new ArrayList<>(); // allocates a single ArrayList object
// the ArrayList contains an array of references (pointers), all null
for(int i=0; i<10; i++){
A temp = new A(i); // allocates a new A
array.add(new A(i)); // stores the pointer to A in the list
}
A fifth = array.get(5); // This object was allocated before, and is unchanged
for(int i=10; i<1000000; i++){
A temp = new A(i); // Allocates a new A
array.add(); // Stores the pointer in the list
// Internally, the List may reallocate its backing array, but it
// is an array of References (pointers), not the A objects themselves
}
System.out.println("it's still alive " + fifth.id); // fifth was allocated in line 4
// and is still reachable
List
从不包含A本身的实例,只引用它们。因此,List的内部内存管理不会影响其内容。
答案 2 :(得分:0)
这是您编辑的答案,因此它只是您问题的补充:
实际上Java中的引用根本不像C ++指针,还有一个额外的间接层 - 对象本身的地址一直在移动(由于压缩垃圾收集),但引用仍然有效。