在软件构造实验过程中,通常要求在声明字段后给出AF,RI和Safety from rep exposure 的描述。
除了要精确记录AF、RI,我们还需要给出表示泄漏的安全声明,关于这一点,通常有以下几种方法:
- All fields are private( final)------即将类中所有的属性(变量)定义为private类型,目的是不让用户得到你的内部属性
- 尽量使用immutable数据类型,比如能使用String就不使用StringBuilder,能使用Instance或
LocalDateTime就不使用Data
如果我们使用了mutable类型的数据(如Set、Map等),为了防止对外泄露其内部表示,通常我们有两种方法:一种是defensive copy,另一种是使用Collections.unmodifiableSet,Collections.unmodifiableMap等方法。
这两种方法有什么区别呢?如果说使用Collections.unmodifiableMap是创建了一个Collections类,那和new一个HashMap的差别其实并不大,可以都称为defensive copy。但实际上,Collection类储存的是地址,并且不能对其中的值进行修改,与defensive copy有本质上的差别。我们可以从代码看看两者的区别。
public class Work{
public static void main(String[] args){
Map<String ,Integer> map=new HashMap<String ,Integer>();
System.out.println("map1 makes defensive copying of map");
System.out.println("map2 is a unmodifuableMap from map");
map.put("a",1);
map.put("b",2);
System.out.println("in map:a matches "+map.get("a"));
Map<String ,Integer> map1=new HashMap<String,Integer>(map);//make defensive copying
map1.put("a", 3);
System.out.println("put(\"a\", 3)in map1");
System.out.println("in map:a matches "+map.get("a"));
System.out.println("in map1:a matches "+map1.get("a"));
Map<String,Integer> map2=Collections.unmodifiableMap(map);//use unmodifiableMap
System.out.println("in map:b matches "+map.get("b"));
System.out.println("in map2:b matches "+map2.get("b"));
System.out.println("put(\"b\", 3)in map2");
map2.put("b", 3);
System.out.println("in map:b matches "+map.get("b"));
System.out.println("in map2:b matches "+map2.get("b"));
}
}
运行程序,控制台输出入如下:
抛出异常的代码为:
map2.put(“b”, 3);
因此对Collections.unmodifiableMap进行变值操作将会抛出java.lang.UnsupportedOperationException异常,这也就解释了为什么使用Collections.unmodifiableSet,Collections.unmodifiableMap等方法可以防止mutable类型的值被外部更改。
捕获异常,结果如图所示: