[英]Does setting an object to null while iterating over a HashMap have any effect on the object's state
我有这个简单的程序,在其中迭代地图并将对象设置为null,而不是在map内部将值更新为null。 我想知道为什么不允许我无效该对象,但是如果我在迭代时更改了该对象的任何值,则对象显示为已更改,请帮助我了解此行为。 (这个问题听起来像是新手)
Map<String, MyObj> map = new HashMap<>();
map.put("a", new MyObj("XYZ"));
map.put("b", new MyObj("FOO"));
map.put("c", new MyObj("BAR"));
System.out.println(map);
// output : {a=sample.MyObj@15db9742, b=sample.MyObj@6d06d69c, c=sample.MyObj@7852e922}
for(Entry<String, MyObj> e : map.entrySet()){
MyObj o = e.getValue();
//set the object to null
o = null;
}
// printing map to see if values are null now.
System.out.println(map);
// output : {a=sample.MyObj@15db9742, b=sample.MyObj@6d06d69c, c=sample.MyObj@7852e922}
这里有两件事在起作用:变量的局部范围,以及与原始类型相比引用类型的行为。
当您拥有for (MyObj i : map.values().toArray(ar))
, i
在for
范围内,仅指向MyObj
实例。 它是参考的副本 。 将i
设置为null时,您只需更改i
的本地值(即副本)即可; 原始引用仍指向原始实例。 由于i
仅指向 MyObj
实例, MyObj
您不会更改MyObj
本身的实例。 确实,当您将某物设置为null
,您只是在说它并不指向某物。 当它为非null时,它指向其类型的实例。
但是,如果你做的东西与 i
,通过调用一个方法也许,你对实例调用它i
点 。 这是因为原始引用和副本都指向同一事物 。 因此,您最终修改了对象本身 。 例如,假设您执行i.setFoo(10)
,那么您将修改i
指向的MyObj
实例, MyObj
该实例上foo
的值设置为10
。
重要的是要了解,对于引用类型 ,只需将变量的值重新分配为null
(或任何其他实例) 就不会修改其指向的对象 。 您要做的只是使变量指向其他内容 (如果为null
,则什么都没有)。
现在,如果您有一个原始数组(例如int[]
),您还将看到相同的东西:
for(int i : intArr) {
i = 10;
}
这不会将intArr
每个位置都设置为10。为什么? 这是因为在这种情况下, i
还是一个局部变量 。 所以这个i
是一个值的副本intArr
。 因此,当您将值重新分配给其他内容时,您只需更改副本的值即可,而不更改原始值。
不,不会。 它不会更改map中的任何内容,因为您正在将null分配给局部变量。 该局部变量以前曾引用过地图值,但现在引用了null,而没有更改地图值本身。
您可以将o
视为一个变量,该变量保存MyObj
实例所在的内存地址。 当您将o = null
写入时,将从o
删除内存地址,但这不会影响MyObj
对象。
在实践中,它有点复杂,但是本质上就是这样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.