不可變類:指這個類的實例一旦建立完成後,就不能改變其成員變量值。如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)); } }