Java-Collections中的unmodifiablexxx方法
目录
Collections中API的分类
unmodifiablexxx方法
代码示例
使用场景举例(个人想法)
Collections中API的分类
Collections中提供了unmodifiablexxx方法,可以获取可变类型的不可变形式
unmodifiablexxx方法
- 这种包装器得到的结果是不可变的:只能看(不可改)
- 但是这种“不可变”是在运行阶段获得的,编译阶段无法据此进行静态检查
——如果报错,只在运行阶段(动态错误)
代码示例
以List为例,通过unmodifiableList获取其不可变形式listCopy
import java.util.ArrayList;import java.util.Collections;import java.util.List;public class collections { public static void main(String[] args) { List list = new ArrayList(); list.add("abcd"); List listCopy = Collections.unmodifiableList(list); //不可变集合 System.out.println(listCopy); listCopy.add("yyyy"); //运行至该步骤报错!! }}
这时候的listCopy只可看,但不可改,如果代码中试图对其进行修改,将在运行阶段报错
不可修改(unmodifiable)的包装器通过截获所有将修改集合的操作并抛出UnsupportedOperationException,剥夺了修改集合的能力
但是,实际上listcopy和list都指向了同一个对象,只是listCopy被限制不可修改;我们仍然可以通过修改list来改变listcopy指向的对象的内容【相当于‘别名’】
import java.util.ArrayList;import java.util.Collections;import java.util.List;public class collections { public static void main(String[] args) { List list = new ArrayList(); list.add("abcd"); List listCopy = Collections.unmodifiableList(list); //不可变集合 System.out.println(listCopy); list.add("xxxxxx"); //通过list修改指向对象的内容 System.out.println(listCopy); //间接达到修改listCopy的目的 }}
运行结果如图所示,listCopy指向对象的内容确实被修改了
使用场景举例(个人想法)
在本例中,Student类只含有一个private final属性namelist,存储学生的名字;只含有相对应的一个get方法,可以获取namelist的内容
import java.util.Collections;import java.util.List;public class Student { private final List namelist = new ArrayList(); public Student()// 构造函数 { namelist.add("loisha"); namelist.add("hpoadam"); } public List getNamelist() {return Collections.unmodifiableList(namelist);//替代防御性拷贝 new ArrayList(namelist) } public static void main(String[] args) { //客户端代码 Student stu = new Student(); List nl = stu.getNamelist(); //通过get方法获取namelist的不可变形式 System.out.println("Student名单:"+nl); nl.add("appp"); //客户端如果尝试改变,就会报错! }}
在getNamelist方法中,返回的是Collections.unmodifiableList(namelist)【namlist的不可变形式】,客户端中用nl接受,故而被限制不可修改nl的内容
这个例子里,getNamelist中使用unmodifiableList的优点在于:实际实现的的效果等同于防御性拷贝,可以防止客户端恶意篡改类中的属性;同时并没有开辟新的内存空间,实现了内存空间上的节约【相较于返回new ArrayList(namelist)——常见的防御性拷贝形式】