-
不可变类是指类的实例一经创建完成,这个实例的内容就不会改变。
-
Java中的String和八个基本类型的包装类(Integer, Short, Byte, Long, Double, Float,Boolean,Char)都是不可变类
3.不可变类 vs 不可变变量:
二者是不一样的。
不可变类是指类的实例内容不会改变,考虑如下代码:
在line 2中我们对s变量进行了再次赋值,实际上是又创建了一个值为”BCD”的String 对象,并将s指向它。变化的是s指向的内存地址(或者简单的叫指针),值为”ABC” 与值为”BCD”的两个String 对象是没有变的。
不可变变量是用Final关键字修饰的变量,考虑如下代码:
我们将s变量用final关键字修饰,这时在s被初始化之后,就无法在line 2 再次给它赋值了,也就是说 我们没办法改变final变量指向的内存地址。
-
所有的成员变量声明为private final,防止初始化后被修改
-
类声明为final,禁止继承,其实是防止类中的方法被重写
-
不为成员变量提供setter方法
-
如果类中包含可变对象,比如一个成员变量是数组,或者其他可变类,那么要有如下操作:
1)在构造方法中,如果构造方法会传入可变对象,我们要使用这个对象的copy来初始化我们的成员变量,而不是直接使用传入的对象。因为传入的是指针,传入的对象在外面可能会被修改,如果直接引用的话会导致我们的成员变量也间接被修改。
2) 在返回这些可变对象的getter方法中,返回对象的copy,而不是直接返回该对象(或者叫该对象的引用/指针)
实例:
下面探讨一下为何类也需要声明为final. 考虑如下代码:
我们把上面Immutable 类的final 声明去掉,ImmutableChild继承了Immutable类,重写了getVArr方法,返回自己的成员变量数组vArr,而这个子类里面的vArr是可变的,在main方法里面初始化时我们给其赋值{3,4},可以看到后面我们改成了{33,44}.
在使用中,任何一个接受Immutable实例的地方都可以接受其子类ImmutableChild实例,并将它作为一个不可变的实例来操作,而实际上它是可变的,这样就有可能出错。
所以把不可变类声明为final是为了防止恶意继承,或者继承中考虑不周密导致的问题。
-
线程安全,省去了加锁的过程,因为对象内容不可变就不用担心线程同时对对象做修改
-
拷贝效率高。当类不可变时, 拷贝其对象只需拷贝指针即可,而不用拷贝对象本身,不用担心会被修改
-
可以作为HashMap的key,类不可变保证了Hashcode的稳定性。
当然,也要注意不可变类在使用过程中可能出现的内存浪费问题,比如大家都知道的最好不要用许多”+”连接String
Original: https://www.cnblogs.com/adeline-tech/p/16655521.html
Author: adeline.pan
Title: Java中如何创建不可变(immutable)类
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/604486/
转载文章受原作者版权保护。转载请注明原作者出处!