【发布时间】:2010-09-27 16:40:31
【问题描述】:
我在 Java 中做以下语句,
Obj t[] = new Obj[10];
Obj a = new Obj("a");
t[0] = a;
a = new Obj("b");
t[1] = a;
为什么在 java 中,当我访问 t[0] 时,它返回我“a”,而不是“b”? 这是因为GC吗?我能相信做这样的手术是安全的吗
【问题讨论】:
我在 Java 中做以下语句,
Obj t[] = new Obj[10];
Obj a = new Obj("a");
t[0] = a;
a = new Obj("b");
t[1] = a;
为什么在 java 中,当我访问 t[0] 时,它返回我“a”,而不是“b”? 这是因为GC吗?我能相信做这样的手术是安全的吗
【问题讨论】:
当你做 t[0] = a;您在数组中分配由 new Object("a") 创建的对象的地址,无论您重复使用 a 变量,都不会更改数组中包含的值。
【讨论】:
问题是,Java 没有指针。
当您将一个对象变量分配给另一个对象变量时,它会更改该变量指向的内容,但不会更改您可能拥有的任何其他引用。
所以:
Object a = new Object("a");
Object b = new Object("b");
a = b;
b = new Object("c");
// At this point, a = "b"
// and b = "c"
如您所见,虽然您首先设置了 a = b,但是当您将 b 设置为新对象时,a 仍然保留对旧对象的引用。
【讨论】:
数组中的值只是一个引用。就像这样做:
Obj a = new Obj("a");
Obj t0 = a;
a = new Obj("b");
最后,t0 变量具有它在第 2 行给出的值 - 即对第 1 行创建的第一个 Obj 的引用。更改 a 变量的值不会t改变t0的值。
了解以上内容后,只需将数组视为变量的集合,例如
Obj[] t = new Obj[10];
大致类似于声明:
Obj t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
(有很多不同之处,但在这个问题的上下文中它们是相似的。)
【讨论】:
这正是正在发生的事情。
Obj t[] = new Obj[10]; // 1
Obj a = new Obj("a"); // 2
t[0] = a;
a = new Obj("b"); // 3
t[1] = a; // 4
您创建了一个数组,该数组可以容纳 10 个对 Obj 实例的引用。打电话给obj01。您将其分配给t。请注意,变量t 和实际对象obj01 的关系非常随意。
您创建一个Obj 的实例,将其称为obj02。您将此对象的引用分配给变量a。请注意,变量a 和实际对象obj02 具有相当随意的关系。
您还将此引用放入t[0]。你在两个地方有一个已知的对象。对象obj02(值为"a")称为a,也称为t[0]。
您创建一个Obj 的实例,调用它obj03。您将这个新对象的引用分配给旧变量a。请注意,变量a 和实际对象obj03 具有相当随意的关系。 a 曾经引用 obj02,但现在不再引用了。
所以,obj01(一个数组)被t引用; obj02(和Obj 的实例)被称为t[0]; obj03(Obj 的一个实例)称为a。
您将a 中的引用放入t[1]。所以,t[1] 获得了对obj03 的引用。
此时所有对象都被范围内的变量引用。由于所有对象都有引用,因此它们不能被垃圾回收。
【讨论】:
为什么在 java 中,当我访问 t[0] 时,它返回的是“a”,而不是“b”?
因为你告诉他用“a”持有对对象的引用。
Java 不直接操作对象。相反,我使用了对象引用。但是这个引用保存了引用的值(不是引用)所以当你将a的值赋给t[0]时,它们都引用了同一个对象。
让我们看看这张图片是否能更好地解释它:
alt text http://img520.imageshack.us/img520/8857/referencesq4.png
首先,a 和 t[0] 引用同一个对象。
稍后删除该引用但 t[0] 没有。
最后 a 和 t1 引用同一个对象,而 t[0] 保持不变。
这是因为 GC 吗?
没有
我能相信做这样的手术是安全的吗
是的
【讨论】: