不可变类:指这个类的实例一旦建立完成后,就不能改变其成员变量值。如JDK内部自带的8个包装类和String类都是不可变类(Interger、Long和String等)都是不可变类。因此不可变类并非指该类是被final修饰的,而是指该类的全部属性是被final修饰的。java
可变类:相对于不可变类,可变类建立实例后能够改变其成员变量值,开发中建立的大部分类都属于可变类。编程
java中自定义不可变类应该遵照以下原则:缓存
使用不可变类的好处?安全
immutable对象也有一个缺点就是会制造大量垃圾,因为他们不能被重用并且对于它们的使用就是”用“而后”扔“,字符串就是一个典型的例子,它会创造不少的垃圾,给垃圾收集带来很大的麻烦。固然这只是个极端的例子,合理的使用immutable对象会创造很大的价值。并发
在JDK中提供了Collections.unmodifiableXXX系列方法来实现不可变集合, 而jdk对不可变集合是经过抛出异常来实现的。可是存在一些问题,下面咱们先看一个具体实例:性能
public class ImmutableTest { @Test public void testJDKImmutable(){ List<String> list=new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); //经过list建立一个不可变的unmodifiableList集合 List<String> unmodifiableList=Collections.unmodifiableList(list); System.out.println(unmodifiableList); //经过list添加元素 list.add("ddd"); System.out.println("往list添加一个元素:"+list); System.out.println("经过list添加元素以后的unmodifiableList:"+unmodifiableList); //经过unmodifiableList添加元素 unmodifiableList.add("eee"); System.out.println("往unmodifiableList添加一个元素:"+unmodifiableList); } } ·············································································· 运行结果: [a, b, c] 往list添加一个元素:[a, b, c, ddd] 经过list添加元素以后的unmodifiableList:[a, b, c, ddd] java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055) at dawn.thread.ImmutableTest.testJDKImmutable(ImmutableTest.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
经过运行结果咱们能够看出:虽然unmodifiableList不能够直接添加元素,可是个人list是能够添加元素的,而list的改变也会使unmodifiableList改变。ui
因此说Collections.unmodifiableList实现的不是真正的不可变集合。线程
Guava提供了对JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava本身的一些专门集合类的immutable实现。当你不但愿修改一个集合类,或者想作一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践。code
注意:每一个Guava immutable集合类的实现都拒绝null值。咱们作过对Google内部代码的全面的调查,而且发现只有5%的状况下集合类容许null值,而95%的状况下都拒绝null值。万一你真的须要能接受null值的集合类,你能够考虑用Collections.unmodifiableXXX。对象
immutable集合能够有如下几种方式来建立:
Guava的immutale集合的简单使用
@Test public void testGuavaImmutable(){ List<String> list=new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); ImmutableList<String> imlist=ImmutableList.copyOf(list); System.out.println("imlist:"+imlist); ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry"); System.out.println("imOflist:"+imOflist); ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b"); System.out.println("imSortList:"+imSortList); list.add("baby"); //关键看这里是否imlist也添加新元素了 System.out.println("list添加新元素以后看imlist:"+imlist); ImmutableSet<Color> imColorSet = ImmutableSet.<Color>builder() .add(new Color(0, 255, 255)) .add(new Color(0, 191, 255)) .build(); System.out.println("imColorSet:"+imColorSet); } ------------------------------------------------------------------------------ 运行结果: imlist:[a, b, c] imOflist:[peida, jerry, harry] imSortList:[a, b, c, d] list添加新元素以后看imlist:[a, b, c] imColorSet:[java.awt.Color[r=0,g=255,b=255], java.awt.Color[r=0,g=191,b=255]]
copyOf方法比你想象的要智能,ImmutableXXX.copyOf会在合适的状况下避免拷贝元素的操做-先忽略具体的细节,可是它的实现通常都是很“智能”的。譬如:
@Test public void testCotyOf(){ ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa"); System.out.println("imSet:"+imSet); //set直接转list ImmutableList<String> imlist=ImmutableList.copyOf(imSet); System.out.println("imlist:"+imlist); //list直接转SortedSet ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet); System.out.println("imSortSet:"+imSortSet); List<String> list=new ArrayList<String>(); for(int i=0;i<=10;i++){ list.add(i+"x"); } System.out.println("list:"+list); //截取集合部分元素 ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 8)); System.out.println("imInfolist:"+imInfolist); } ---------------------------------------------------------------------------- 运行结果: imSet:[peida, jerry, harry, lisa] imlist:[peida, jerry, harry, lisa] imSortSet:[harry, jerry, lisa, peida] list:[0x, 1x, 2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x] imInfolist:[2x, 3x, 4x, 5x, 6x, 7x]
public class ImmutableExample3 { private final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3); private final static ImmutableSet set = ImmutableSet.copyOf(list); private final static ImmutableMap<Integer, Integer> map = ImmutableMap.of(1, 2, 3, 4);//map必须成对出现(偶数个) private final static ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder().put(1, 2).put(3, 4).put(5, 6).build(); public static void main(String[] args) { System.out.println(map2.get(3)); } }