引言
在我们编写java代码的过程中,总是少不了类实例化对象的创建。
有的对象创建之后值可以改变,例如List,Map;
有的对象创建之后值不可以被改变,例如String;
不可变类型与可变类型的区别客观存在。
为什么要有不可变类型(immutable)
从直觉来看,不可变类型可能有点自缚手脚,但在编写代码时,不可变带来的约束可以确保代码更少出现逻辑上的错误。
实际编写代码过程中,常常会保持一些数据不变的需要。例如存储外部的原始输入,存储一个逻辑上确定的数据,比如常识性知识;在类的层面实现不可变,很大程度上方便了代码的开发。
如何实现不可变类型
试想一下几种场景:
1.编写一个矩阵转置函数,输入一个矩阵,输出它的转置;
2.编写一个排序算法,输入一个数组,输出一个已经排序的数组;
在这两个例子中,如果输入之后还可能再次被引用,我们应该输出一个新的矩阵、数组,保持原先输入不变。
再试想一下另外一些场景:
1.编写一个类,内部有List存储用户输入的数据,编写get方法返回这个数组;
如果不希望通过类方法调用之外的操作改变List中的元素,get方法应该返回List的复制。
上边些场景中,返回的值都是原有数据结构经过复制得来的。是否复制原有数据,实现了不同的功能。这种实现不可变类型的必要手段叫做防御式拷贝。
另一种实现不可变类型的必要手段是通过关键字进行约束。使用private 关键字修饰所有可变的内部数据结构,让外部不能访问到,外界自然无法使原本不可变的类型做出改变。更进一步,还可在数据结构定义时加入final关键字,主动避免一些编写时产生的错误。