首页 > 解决方案 > 在java中不可变对象的情况下,浅拷贝是否可以作为深拷贝工作?

问题描述

我在实践中阅读java并发。我遇到了这个片段,这让我有些困惑。 如果需要车队的不变视图,getLocations 可以改为返回位置图的浅表副本。由于 Map 的内容是不可变的,所以只有 Map 的结构,而不是内容必须被复制。

public Map<String,Point> getLocations(){
 return Collections.unmodifiableMap(new HashMap<String,Point>(locations));
}

返回车辆位置的不可修改但实时视图

public Map<String,Point> getLocations(){
return unmodifiableMap; //unmodifiableMap = Collections.unmodifiableMap(locations);
}
public class Point{
 public final int x,y;
 public Point(int x, int y){
  this.x = x;
  this.y=y;
 }
}
public void setLocation(String id,int x,int y){
 if(locations.replace(id,new Point(x,y==null)
   //throw exception for invalid vehicle
}

这是否意味着new HashMap<String,Point>(locations)正在对位置图进行深层复制,并在复制发生时通过为 Point 创建一个新对象来分配新的引用。浅拷贝不应该new HashMap<String,Point>(locations)保留对 Point 对象的原始引用,并且更改在所有线程中都是可见的。

标签: javahashmap

解决方案


不需要深拷贝,因为 Point 对象是不可变的,无法更改。这是断言的:

由于 Map 的内容是不可变的

如果 Point 对象是可变的,您实际上必须进行深层复制。

如果 getLocations 是指对地图“结构”变化的可见性,则两种实现之间的区别。第一个实现返回地图副本的不可修改视图。如果在方法返回后添加或删除位置,则在此方法返回的地图中将不可见。第二个返回地图本身的不可修改视图。方法返回后所做的任何更改将对调用者可见。


推荐阅读