回答
在我们调用 ConcurrentHashMap
的 put()
时,ConcurrentHashMap
会校验 key 和 value 是否为 null,如果为 null 就抛出 NullPointerException,如下:
为什么要这么设计呢?大明哥认为主要有如何几个原因。
一、避免多线程下的二义性
null
是一个特殊的值,表示没有对象或者引用。在 ConcurrentHashMap
中如果 key 或者 value 为 null,当我们通过 get(key)
获取对应的 value的时候,如果返回的结果是 null
,我们是没有办法判断的,它是 put(k,v)
的时候,value 本身为 null 值,还是这个 key 本身就不存在呢?
在并发编程中,一致性和可预测性非常重要。如果一个线程试图通过 get(key)
获取 key 的值时,而这个 key 尚未被任何线程写入,那它应该返回什么呢?
如果返回null
,那么这个返回值是表示 key 不存在,还是 key 的值就是null
?这样的歧义会使得并发编程更加复杂且容易出错。
那有小伙伴就说为什么 HashMap
允许为 key 和 value 为 null 呢?因为 HashMap
是并发不安全的呀,它不需要保证一致性和可预测性。
二、简化内容设计
ConcurrentHashMap
使用 CAS 来保证高效的并发能力,如果允许 null
作为 key
,会使得 ConcurrentHashMap
操作更加复杂,因为为了避免出现空指针,ConcurrentHashMap
中的大多数操作都需要额外检查null
,并做适当的处理。通过禁止null
,可以简化这些实现,降低错误的风险,同时提高整体性能。