TreeMultimap未抛出预期NullPointerException的原因排查
这个问题的核心是你误解了NullPointerException的抛出时机——它根本不是在map.put()执行时抛出的,而是调试器在尝试展示map内容时触发的!
让我一步步拆解原因:
TreeMultimap的put逻辑不依赖value的hashCode
TreeMultimap底层用TreeMap存储键,每个键对应的value集合是TreeSet(因为它是有序Multimap)。TreeSet在添加元素时,完全依赖compareTo方法来确定元素的位置和唯一性,不会调用hashCode方法。你的House类的compareTo方法直接返回1,没有访问任何null字段,所以map.put(3L, new House())这一步执行得完全顺畅,不会抛出任何异常,代码自然会继续走到第2行打印"done"。调试器里的NPE来自toString()调用
你在调试时看到的NPE,是调试器为了显示map的内容,自动调用了map.toString()方法导致的。Guava的Multimap的toString实现会遍历所有键值对,在这个过程中间接触发了House的hashCode方法。此时House的numberOfRooms_是null,调用它的hashCode()就会抛出NPE,但这个异常是发生在调试器的线程中,和你的应用程序主线程完全无关,所以不会中断你的代码执行。验证结论的小实验
如果你在代码里手动添加一行System.out.println(map);,你会发现这时候才会真正抛出NPE——因为这时候是你的应用程序线程在调用toString(),触发了hashCode的执行。
另外提个小建议:你的House类实现Comparable时最好指定泛型,写成implements Comparable<House>,避免不必要的类型转换问题。
内容的提问来源于stack exchange,提问作者Rishiraj Das

