在文章:Mybatis源碼解析,一步一步從淺入深(五):mapper節點的解析中mybatis的源碼中用到了Collections.unmodifiableList方法,其實還有unmodifiableMap,unmodifiableSet兩個類似的方法,接下來就分析一下。html
unmodifiableMap,unmodifiableList,unmodifiableSet都是Collections的靜態方法。能夠明顯看到三個方法都是unmodifiable開始的。java
unmodifiable的中文意思是:不可更改,不可修改的。那麼這三個方法到底有什麼用呢?想必你已經有一個大概的猜想了。記住你的猜想,先來看一段代碼:mybatis
一,使用示例 app
1 public void testUnmodifiable() { 2 Map map = new HashMap(); 3 map.put("name", "zhangchengzi"); 4 map.put("age", 20); 5 6 System.out.println("map before:"+map);//打印結果:map before:{name=zhangchengzi, age=20} 7 8 Map unmodifiableMap = Collections.unmodifiableMap(map); 9 System.out.println("unmodifiableMap before:"+unmodifiableMap);//打印結果:unmodifiableMap before:{name=zhangchengzi, age=20}。 10 11 System.out.println("年齡:"+unmodifiableMap.get("age"));//打印結果:年齡:20 12 //修改年齡 13 unmodifiableMap.put("age", 28); 14 15 System.out.println("map after:"+map); 16 System.out.println("unmodifiableMap after:"+unmodifiableMap); 17 }
相信你代碼都看的很明白,那麼後面兩個爲何沒有打印出結果呢?由於在13行拋出 了異常:eclipse
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
at com.test.learnmybatis.UserDaoTest.testUnmodifiable(UserDaoTest.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
那麼unmodifiableMap方法的做用就是將一個Map 進行包裝,返回一個不可修改的Map。若是調用修改方法就會拋出java.lang.UnsupportedOperationException異常。ide
一樣的道理unmodifiableList,unmodifiableSet就是將一個List或則Set進行包裝,返回一個不可修改的List或者Set。你猜對了嗎?那麼unmodifiableMap是怎麼作到這些事情的呢?工具
二,unmodifiableMap方法源碼解讀: post
上面提到過unmodifiableMap是Collections工具類的一個靜態方法: lua
/** * 返回一個指定Map的不可修改的視圖,這個方法返回的視圖爲用戶提供內部Map的"只讀"訪問, * 對是返回視圖執行「讀取」操做會直接做用到指定的Map, * 同時若是對返回視圖執行修改操做(不管是直接的仍是間接的)都會返回異常:UnsupportedOperationException * Returns an unmodifiable view of the specified map. This method * allows modules to provide users with "read-only" access to internal * maps. Query operations on the returned map "read through" * to the specified map, and attempts to modify the returned * map, whether direct or via its collection views, result in an * <tt>UnsupportedOperationException</tt>.<p> * * 若是指定的Map是可序列化的,則返回的Map也將是可序列化的。 * The returned map will be serializable if the specified map * is serializable. * * @param <K> the class of the map keys * @param <V> the class of the map values * @param m the map for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified map. */ public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) { return new UnmodifiableMap<>(m); }
看源碼的註釋已經作了解釋說明,可是尚未涉及到具體「不可修改的」原理,咱們接着看源碼。這個Collections.unmodifiableMap方法中,使用參數Map 實例化了一個UnmodifiableMap。咱們看一下這個類:spa
1,UnmodifiableMap類實現了Map接口,而且在這個類中有一個final修飾的 Map 類型的屬性m。在構造方法中將調用Collections.unmodifiableMap(map)方法中傳入的map實參,賦值給了UnmodifiableMap類的m屬性。
2,上面在unmodifiableMap方法的註釋中提到,對返回視圖的修改,直接指向指定的map。爲何呢?看UnmodifiableMap的get方法,能夠清晰看到,get方法直接到用了m.get(key)方法。
3,同時最關鍵的是「不可修改」是怎麼實現的。看UnmodifiableMap的put方法,也能夠很清晰的看到 在put方法中直接拋出了UnsupportedOperationException。
到這裏Collections.unmodifiableMap方法的分析就進行完了,總結一下Collections.unmodifiableMap方法返回一個不可修改的Map。
三,unmodifiableList,unmodifiableSet
unmodifiableList,unmodifiableSet的做用和實現原理和unmodifiableMap的是同樣的,有興趣就本身去看一下源碼吧。
原創不易,轉發請註明出處:http://www.javashuo.com/article/p-utdxmwkt-bu.html