在文章:Mybatis源码解析,一步一步从浅入深(五):mapper节点的解析中mybatis的源码中用到了Collections.unmodifiableList方法,其实还有unmodifiableMap,unmodifiableSet两个相似的方法,接下来就分析一下。

unmodifiableMap,unmodifiableList,unmodifiableSet都是Collections的静态方法。可以明显看到三个方法都是unmodifiable开始的。

unmodifiable的中文意思是:不可更改,不可修改的。那么这三个方法到底有什么用呢?想必你已经有一个大概的猜测了。记住你的猜测,先来看一段代码:

一,使用示例  

 public void testUnmodifiable() {
Map map = new HashMap();
map.put("name", "zhangchengzi");
map.put("age", 20); System.out.println("map before:"+map);//打印结果:map before:{name=zhangchengzi, age=20} Map unmodifiableMap = Collections.unmodifiableMap(map);
System.out.println("unmodifiableMap before:"+unmodifiableMap);//打印结果:unmodifiableMap before:{name=zhangchengzi, age=20}。 System.out.println("年龄:"+unmodifiableMap.get("age"));//打印结果:年龄:20
//修改年龄
unmodifiableMap.put("age", 28); System.out.println("map after:"+map);
System.out.println("unmodifiableMap after:"+unmodifiableMap);
}

相信你代码都看的很明白,那么后面两个为什么没有打印出结果呢?因为在13行抛出 了异常:

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异常。

同样的道理unmodifiableList,unmodifiableSet就是将一个List或则Set进行包装,返回一个不可修改的List或者Set。你猜对了吗?那么unmodifiableMap是怎么做到这些事情的呢?

二,unmodifiableMap方法源码解读: 

  上面提到过unmodifiableMap是Collections工具类的一个静态方法: 

  

    /**
* 返回一个指定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。我们看一下这个类:

  

  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的是一样的,有兴趣就自己去看一下源码吧。


原创不易,转发请注明出处:https://www.cnblogs.com/zhangchengzi/p/9685918.html

Collections.unmodifiableMap,Collections.unmodifiableList,Collections.unmodifiableSet作用及源码解析的更多相关文章

  1. SpringtMVC中配置 <mvc:annotation-driven/> 与 <mvc:default-servlet-handler/> 的作用与源码解析

    基于 Spring4.X 来学习 SpringtMVC, 在学习过程中,被"告知"在 XML 配置文件中建议设置如下两项: 一直不明白为什么,但又甘心.于是,花了一点时间来调试源码 ...

  2. Flink 源码解析 —— Flink JobManager 有什么作用?

    JobManager 的作用 https://t.zsxq.com/2VRrbuf 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac ...

  3. Flink 源码解析 —— Flink TaskManager 有什么作用?

    TaskManager 有什么作用 https://t.zsxq.com/RZbu7yN 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- ...

  4. Collections.synchronizedList 、CopyOnWriteArrayList、Vector介绍、源码浅析与性能对比

    ## ArrayList线程安全问题 众所周知,`ArrayList`不是线程安全的,在并发场景使用`ArrayList`可能会导致add内容为null,迭代时并发修改list内容抛`Concurre ...

  5. Collections.unmodifiableMap

    1. Collections.unmodifiableMap 是什么? Java的官方解释: public static <K,V> Map<K,V> unmodifiable ...

  6. java.util.Collections.unmodifiableMap 示例

    1. 概述 public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m) ...

  7. Java集合【5】-- Collections源码分析

    目录 一.Collections接口是做什么的? 二.Collections源码之大类方法 1.提供不可变集合 2.提供同步的集合 3.类型检查 4.提供空集合或者迭代器 5.提供singleton的 ...

  8. (二)一起学 Java Collections Framework 源码之 AbstractCollection

    . . . . . 目录 (一)一起学 Java Collections Framework 源码之 概述(未完成) (二)一起学 Java Collections Framework 源码之 Abs ...

  9. 关于Collections.sort()排序方法的源码探索

    /**下面在自己代码中使用Collections.sort()方法去比较Student对象,通过在自己写的类里面通过匿名内部类实现Comparator接口,这个接口是让你自己实现比较器的规则*/ // ...

随机推荐

  1. 微服务SpringCloud之Spring Cloud Config配置中心服务化

    在前面两篇Spring Cloud Config配置中心的博客中都是需要指定配置服务的地址url:spring.cloud.config.uri,客户端都是直接调用配置中心的server端来获取配置文 ...

  2. 持续集成高级篇之Jekins参数化构建(二)

    系列目录 上一节我们讲解了如何使用bat脚本或者powershell脚本自身的机制来达到参数化构建的目的,这在一定程序上增加了灵活性,然而缺点也相当明显:它只能适应一些相对比较固定的参数传入(比如像上 ...

  3. Codeforces 255C

    题意略. 本题考查动态规划,顺便考查一下优化. 这个题目可以归约到最长递增子序列那一类,定义状态:dp[i][j] --- 当前以第i个数结尾,前一个数是第j个数的最长序列. if(a[i] == a ...

  4. Salesforce LWC学习(五) LDS & Wire Service 实现和后台数据交互 & meta xml配置

    之前的几节都是基于前台变量进行相关的操作和学习,我们在项目中不可避免的需要获取数据以及进行DML操作.之前的内容中也有提到wire注解,今天就详细的介绍一下对数据进行查询以及DML操作以及Wire S ...

  5. java学习之String类

    标签(空格分隔): String类 String 的概述 class StringDemo{ public static void main(String[] args){ String s1=&qu ...

  6. ElasticSearch专栏

    1.es的分布式架构原理(es是如何实现分布式)? elasticsearch设计的理念就是分布式搜索引擎,底层其实还是基于lucene的.核心思想就是在多台机器上启动多个es进程实例,组成了一个es ...

  7. hdu-6638 Snowy Smile

    题目链接 Snowy Smile Problem Description There are n pirate chests buried in Byteland, labeled by 1,2,-, ...

  8. POJ-2155-Matrix二位树状数组应用

    题目: 一个只有0和1构成的二维平面,给你两种指令,一种是区间的更新,即0变为1,1变为0:一种是查询一个点是1还是0: 由于是二进制,所以每次更新在相应的点上加一,最后对2取余即可. 至于二维的树状 ...

  9. NOIP 2016 蚯蚓 题解

    一道有趣的题目,首先想到合并果子,然而发现会超时,我们可以发现首先拿出来的切掉后比后拿出来切掉后还是还长,即满足单调递增,故建立三个队列即可. 代码 #include<bits/stdc++.h ...

  10. vim 同时操作多行

    使用 vim 的时候,经常会有同时注释或解开注释的情况,逐行编辑很浪费时间,下面的同时操作多行的方式 删除操作 control+v 进入 visual block 模式 选中要删除几行文字 d删除 插 ...