【问题标题】:Does ArrayList Actually Stores references onlyArrayList 实际上只存储引用吗
【发布时间】:2016-03-09 03:58:54
【问题描述】:
Java 将对象引用存储在数组中的所有地方我都读过它。甚至我自己也证明了这一点。
但是后来我改变了对象的状态,这意味着我改变了属性的值并保存在数组中,我可以检索同一个对象的多个状态。如果 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。我很迷惑!
【问题讨论】:
标签:
java
arrays
object
memory-management
reference
【解决方案1】:
看看这段代码:
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 仅包含引用。如果您从列表中检索对象并更改其中的某些内容,则原始对象也会被更改
【解决方案2】:
回答你的问题。是的。所有变量都只是对对象位置的引用,而不仅仅是 ArrayList。写入MyObject obj = new MyObject(); 会创建一个新对象,但变量obj 只是对该对象在堆(也称为内存)中位置的引用。
ArrayList(不看它的实际实现)只是将每个对对象位置的引用存储为 ArrayList 的索引而不是唯一变量。
更详细一点:您需要了解创建对象的每个部分的作用。试着用这种方式想象它:
每个对象都位于一个内存地址中,该地址占用了其所有字段使用的字节数。假设我们有一个名为 MyObject 的对象,它占用 100 个字节。当我们使用new 关键字(即new MyObject())创建对象时,它存储在堆中的内存位置(这是为您的程序留出的内存区域,用作动态内存分配)。让我们说,当这个对象被创建时,它占用了 1000 个内存空间(最多 1100 个,因为它使用了 100 个字节的内存)。所以:
|我的对象|
1000
当我们编写MyObject obj 时,它会在堆栈中留出内存(用于静态内存分配),这将保存对象的位置。所以它可能会在它自己的位置保存对对象位置的引用,我们将假装它被标记为 4
|______|
4
当我们把 2 条指令放在一起写 MyObject obj = new MyObject() 时,它会将对象的地址放入变量的内存位置,所以我们最终得到:
|我的对象|
1000
|1000|
4