Collections.unmodifiableMap源码解析

Collections.unmodifiableMap源码解析

Collections.unmodifiableMap

其实还有unmodifiableList,unmodifiableSet两个相似的方法,接下来就分析一下。

unmodifiable

unmodifiable的中文意思是:不可更改,不可修改的。
接下来我们来看看此处的unmodifiableMap和我们平常使用的map有什么不同。
public class UnmodifiableMapTest {

    @Test
    public void testUnmodifiableMap() {
        //我们平常使用的hashMap
        Map<String, Object> generalMap = new HashMap<>();
        //我们平常都这么用
        generalMap.put("i'm generalMap", "bling");
        //调用Collections的静态方法返回了一个unmodifiableMap
        Map<String, Object> unmodifiableMap = Collections.unmodifiableMap(generalMap);
        //我们继续往map里塞值
        unmodifiableMap.put("i'm unmodifiableMap", "kkk");
    }
}

我们运行一下,

java.lang.UnsupportedOperationException
	at java.util.Collections$UnmodifiableMap.put(Collections.java:1457)
	at cn.magfin.devastator.UnmodifiableMapTest.testUnmodifiableMap(UnmodifiableMapTest.java:26)
	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:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

可以看到当我们想要往unmodifiableMap里继续塞值的时候抛出了一个异常,不被支持的操作!
我们接下来来看一下,这个unmodifiableMap静态方法里面到底做了什么处理:

 public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
        return new UnmodifiableMap<>(m);
    }

这里创建了一个新的UnmodifiableMap,并且使用我们原先创建的普通的map作为构造参数,我们继续往下:

  private final Map<? extends K, ? extends V> m;

  UnmodifiableMap(Map<? extends K, ? extends V> m) {
           if (m==null)
               throw new NullPointerException();
           this.m = m;
       }

这里简单的对参数进行了判空防止产生NPE,随后将我们的map赋给了一个由final修饰的变量m并且作为我们先前调用的静态方法unmodifiableMap的返回值.

到这里还是不能解释为什么我们调用put方法的时候会抛出异常.我们接着往下看当我们调用put的时候发生了什么事情.
public V put(K key, V value) {
            throw new UnsupportedOperationException();
        }

可以看到,当我们直接使用unmodifiableMap的put方法的时候,直接抛出了一个UnsupportedOperationException异常.

        public boolean isEmpty()                 {return m.isEmpty();}
        public boolean containsKey(Object key)   {return m.containsKey(key);}
        public boolean containsValue(Object val) {return m.containsValue(val);}
        public V get(Object key)                 {return m.get(key);}
当我们调用unmodifiableMap.get(key)方法的时候,就变相的调用了我们原先的map的get(key)方法,并且还有其他几个map相关的操作方法都是这么实现的.

最后补充说明:

final Map<String, Object> finalMap = new HashMap<>();

Map<String, Object> unmodifiableMap = Collections.unmodifiableMap(generalMap);

此处的finalMap != unmodifiableMap,这两者是没有任何关系的,前者是不能重新更改对象引用的,但是后者完全不受影响,你完全可以更改unmodifiableMap的引用,比如:

	Map<String, Object> unmodifiableMap = new hashMap<>();

但是如此一来这个"新的"unmodifiableMap已经不再具有unmodifiable的特性了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值