定义
- 可变类:类的实例变量创建后,其成员变量可以再赋值
- 不可变类:类的实例变量创建后,其成员变量不可更改
特点
-
安全
在
多线程
情况下,一个可变对象的值很可能被其他进程改变,这样会造成不可预期的结果,而使用不可变对象就可以避免这种情况同时省去了同步加锁等过程,因此不可变类是线程安全的。 -
不安全
密码
应该存放在字符数组中而不是String中:由于字符串被放在字符串缓冲池中以方便重复使用,所以它就可能在内存中被保留很长时间,而这将导致安全隐患,因为任何能够访问内存(memory dump内存转储)的人都能清晰的看到文本中的密码 -
时间高效
当一个对象是不可变的,那么需要
拷贝
这个对象的内容时,就不用复制它的本身而只是复制它的地址,复制地址(通常一个指针的大小)只需要很小的内存空间,具有非常高的效率。同时,对于引用该对象的其他变量也不会造成影响。
此外,不变性保证了hashCode 的唯一性,因此可以放心地进行缓存而不必每次重新计算新的哈希码。而哈希码被频繁地使用, 比如在hashMap 等容器中。将hashCode 缓存可以提高以不变类实例为key的容器的性能。 -
空间浪费
不可变类的每一次“改变”都会产生新的对象,因此在使用中不可避免的会产生很多垃圾。
创建
- 所有成员都是
private final
的,private保证其他人不能对普通类型成员的值和对象成员的成员变量进行改动(如String的char[]内的元素),final保证普通类型成员变量的值和对象成员变量的指针对任何人都不可改(当然不写final,小心一点也可以保证不改,但是,写上final起到了保证作用) - 提供带参数的构造器,用于根据传入参数来初始化类里的成员变量
- 不用提供对成员的改变方法,例如:setXXXX,因为设置了也没用
- 确保所有的
方法不会被重载
。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。 - 如果某一个类成员不是基本类型(primitive type)或不可变类,必须通过在成员初始化(in)或者getter方法(out)时通过深度拷贝(即复制一个该类的新实例而非引用)方法,来确保类的不可变。
- 如果有必要,重写hashCode和equals方法,同时应保证两个用equals方法判断为相等的对象,其hashCode也应相等。
为什么要按照上述方法创建不可变类?
在java中String类为什么要设计成final?
例子
Java 中八个基本类型的包装类
和 String
类都属于不可变类,而其他的大多数类都属于可变类。
参考文献
https://blog.csdn.net/fw0124/article/details/49659717 JAVA的可变类与不可变类