1、典型回答
浅层次的来回答这个问题的答案是,JDK 源码不支持 Hashtable 插入 value 值为 null,如以下JDK 源码所示:
也就是JDK 源码规定了,如果你给 Hashtable 插入 value 值为 null 就会抛出空指针异常
并目看上面的JDK 源码可以得出结论,如果 key 也为 null 的时候,因为 null 没有 hashCode 所以它也会报空指针异常,如下图所示:
2、全面剖析
简单来说,Hashtable 之所以 key 不允许为 null,和 value 不允许为 null 的原因是,JDK 源码级别做了限制,如果 Hashtable 的 key 或者 value 为 null 就会报空指针异常。
3、知识扩展
但是,我们看JDK 源码不难发现,这些判断和错误 Hashtable 完全可以在后续的 JDK 版本中修复和调整代码,可以让其支持 key 和 value 都为 null,为什么它没有修复这个问题呢?
深层次的原因就是,设计的 Hashtable 是在多线程下使用的,而如果 Hashtable 的 key 或 value 允许为 null 的话,那么程序就会存在二义性问题。
什么是二义性问题?
所谓的二义性问题是指含义不清或不明确。
如果我们假设 Hashtable 允许插入 null,那么此时它就会有二义性问题,这个 null 值就有两层含义
- 这个 key 不存在,所以返回 null。
- key 存在,并且值本身就为 null,所以返回的就是 null
而在多线程下,你没有办法证明真伪,因为你在判断证明的时候,其他线程可能同时做了修改,所以不能被证明的二义性问题需要从源头上杜绝,所以多线程下的 Hashtable 是不允许 key 和 value 插入 null 值的
ConcurrentHashMap 也是不允许插入 null,原因和 Hashtable 是一样的 (因为有二义性问题)。
为什么 HashMap 允许插入 null 值?
因为 HashMap 设计是在单线程下使用的,而单线程可以证明真伪,它在进行查询判断的时候,不用担心有其他线程对这个值同时做修改,所以它不存在二义性问题,所以 HashMap 允许 key 和 value 都为 null。