繁体   English   中英

在迭代HashMap时将对象设置为null是否对对象的状态有任何影响

[英]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))ifor范围内,仅指向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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM