ArrayList实际存储仅引用

时间:2015-12-04 09:13:45

标签: java arrays object memory-management reference

我已经在任何地方读过Java,它在数组中存储了Object引用。甚至我自己也证明了这一点 但后来我改变了对象的状态,意味着我改变了属性的值并保存在数组中,我可以检索同一对象的多个状态。如果Array仅保存引用,那么引用如何保存状态。 例如:

class Test{
String id;
}
Test[] testArr = new Test[2];
test = new Test();
test.id = "ABC"
testArr.add(test)
test.id = "XYZ"
testArr.add(test)

现在如果我们只存储引用,那么第二次赋值将覆盖测试对象的id值,并且数组中的两个条目都具有相同的id值,但事实并非如此,我们可以检索id值ABC和XYZ。我很迷惑!

2 个答案:

答案 0 :(得分:0)

回答你的问题。是。所有变量都只是对对象位置的引用,而不仅仅是ArrayList。编写MyObject obj = new MyObject();会创建一个新对象,但变量obj只是对该对象在Heap(aka内存)中的位置的引用。

ArrayList(不查看其实际实现)只是将每个对象的位置的引用存储为ArrayList的索引而不是唯一的变量。

更详细一点:您需要了解创建对象的每个部分的作用。试着以这种方式想象它:

每个对象都位于一个占用其所有字段使用的字节数的内存地址中。让我们假设我们有一个名为MyObject的对象占用100个字节。当我们使用new关键字创建一个Object(即。new MyObject())时,它存储在堆中的一个内存位置(这是为程序留出的内存区域,用作动态内存分配) )。让我们说当创建这个对象时,它会占用内存空间1000(最多1100,因为它使用100个字节的内存)。所以:

| 为MyObject | < - 这是存储空间的可视化
   1000

当我们写MyObject obj时,它会在堆栈中留出内存(用于静态内存分配),这将保存对象的位置。因此,它可以保留对象在其自己位置的位置的引用,我们将假装标记为4

| ______ | < - 空记忆位置,因为它尚未分配。
4

当我们将2条指令放在一起并写入MyObject obj = new MyObject()时,它会将对象的地址放入变量的内存位置,因此我们最终得到:

| 为MyObject | < - 实际对象的位置
1000

| 1000 | < - 引用对象位置的变量的位置
4

答案 1 :(得分:0)

看看这段代码:

class Test {
    String id = "A";
}

public class Main {

    public static void main(String[] args) {
        ArrayList<Test> list = new ArrayList<Test>();

        // Adding some Test Object to the list.
        Test foo = new Test();
        list.add(foo);
        System.out.println("Value of foo id: " + foo.id);

        // Retrieving the Object from the list & changing the value
        Test bar = list.get(0);
        bar.id = "B";

        System.out.println("Value of foo id: " + foo.id);
    }
}

输出:

Value of foo id: A
Value of foo id: B

正如您所见,arraylist只保留引用。如果从列表中检索对象并更改其中的内容,则原始对象也将更改