将一个类改造成不可变类,来解决线程安全问题。
实现不可变类的一些思路:
使用final关键字修饰所有成员变量,避免其被修改,也可以保证多线程环境下被final关键字修饰的变量所引用的对象的初始化安全,即final修饰的字段在其他线程可见时,必定是初始化完成的。
1.
使用private修饰所有成员变量,可以防止子类及其他地方通过引用直接修改变量值。
1.
禁止提供修改内部状态的公开接口(比如我们前面例子中的setXY方法)
1.
使用final修饰类,禁止不可变类被外部继承,防止子类改变其定义的方法的行为。
1.
如果类中存在数组或集合,在提供给外部访问之前需要做防御性复制
public final class DefensiveDemo {
private final List<Integer> list = new ArrayList<Integer>();
public DefensiveDemo(){
list.add(1);
list.add(2);
list.add(3);
}
public List<Integer> getData(){
return list;
}
public static void main(String[] args) {
DefensiveDemo defensiveDemo = new DefensiveDemo();
List<Integer> data = defensiveDemo.getData();
data.add(4);
}
}
代码中能够对集合修改,不能保证不可变对象。
public List<Integer> getData(){
// return list;
return Collections.unmodifiableList(new ArrayList<Integer>(list));
}
Exception in thread "main" java.lang.UnsupportedOperationException
使用Collections.unmodifiableList方法进行包装,这样能保证外部无法修改(添加元素)我们返回的结果,那么DefensiveReplicaDemo的data集合的值永远会是1,2,3。
public class DeepCopyObjectTest {
public static void main(String[] args) {
Map<Integer,Student> map = Maps.newHashMap();
map.put(1,new Student("xiaoli",18));
// copy(map);
// deepCopy(map);
baseCopy();
}
public static void copy(Map<Integer,Student> map){
System.out.println(map.get(1).getName());
Map<Integer,Student> newMap = Collections.unmodifiableMap(map);
newMap.get(1).setName("xiaowang");
System.out.println(map.get(1).getName());
}
public static void deepCopy(Map<Integer,Student> map){
Map<Integer,Student> newMap = new HashMap<>(map.size());
for (Map.Entry<Integer,Student> entry:map.entrySet()) {
newMap.put(entry.getKey(),new Student(entry.getValue()));
}
newMap.put(2,new Student("xiaosun",20));
Map<Integer,Student> result = Collections.unmodifiableMap(newMap);
result.get(1).setName("xiaozhao");
System.out.println(result.get(1).getName());
System.out.println(map.get(1).getName());
//Exception in thread "main" java.lang.UnsupportedOperationException
//result.put(2,new Student("xiaosun",20));
}
public static void baseCopy(){
Map<Integer,String> isMap = Maps.newHashMap();
isMap.put(1,"a");
isMap.put(2,"b");
Map<Integer,String> isMapCopy = Collections.unmodifiableMap(isMap);
// Exception in thread "main" java.lang.UnsupportedOperationException
// isMapCopy.put(1,"aa");
//Exception in thread "main" java.lang.UnsupportedOperationException
// isMapCopy.put(3,"c");
isMap.put(1,"aa");
isMap.put(3,"c");
System.out.println(isMap);//{1=aa, 2=b, 3=c}
System.out.println(isMapCopy);//{1=aa, 2=b, 3=c}
//== 是比较内存地址是否相同,equals 是比较内存地址上面的值是否相同
System.out.println(isMap == isMapCopy);
System.out.println(isMap.equals(isMapCopy));
}
}
返回指定有序映射的不可修改视图。此方法允许模块为用户提供对内部有序映射的“只读”访问。在返回的有序映射上执行的查询操作将“读完”指定的有序映射。试图修改返回的有序映射(无论是直接修改、通过其 collection 视图修改,还是通过其 subMap、 headMap或 tailMap视图修改)将导致抛出 UnsupportedOperationException。
就是说unmodifiableMap不能添加新的元素,并不能对基本类型进行修改。
Map<Integer,StringBuilder> unmodifiableMap=Collections.unmodifiableMap(map);
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/mingyuli/article/details/120375906
内容来源于网络,如有侵权,请联系作者删除!