Java8空安全比较问题:产品vintage属性对比时触发NPE
解决IProduct对象vintage属性空安全比较的问题
哦,我懂你遇到的坑了!Comparator.nullsLast(...)的用法很容易搞混——它默认是用来处理被比较的对象本身为null的情况,而不是对象内部的属性为null。这就是你为啥还会碰到NPE的原因。
问题根源
假设你之前的代码大概是这样的:
@Override public int compare(IProduct product1, IProduct product2) throws ProductComparisonException { return Comparator.nullsLast(Comparator.comparing(IProduct::getVintage)) .compare(product1, product2); }
这里的nullsLast只会处理product1或product2本身为null的场景,但当两个产品对象都不为null,其中一个的vintage属性是null时,Comparator.comparing(IProduct::getVintage)会直接调用vintage自身的compareTo方法,这时候null就会触发NPE。
正确的空安全写法
你需要在属性层面也套一层空安全比较器,也就是给comparing方法的第二个参数传入处理null的比较器:
场景1:需要同时处理产品对象为null和vintage属性为null
@Override public int compare(IProduct product1, IProduct product2) throws ProductComparisonException { // 外层nullsLast处理product对象本身为null的情况 Comparator<IProduct> productComparator = Comparator.nullsLast( // 内层nullsLast处理vintage属性为null的情况 Comparator.comparing( IProduct::getVintage, Comparator.nullsLast(Comparator.naturalOrder()) ) ); return productComparator.compare(product1, product2); }
这段代码的逻辑是:
- 如果其中一个product是null,会被排在最后
- 如果product都不为null,就比较它们的vintage:vintage为null的排在后面,非null的按自然顺序比较
场景2:确保product对象永远不为null,只需要处理vintage属性为null
如果你的业务逻辑里已经保证product1和product2不会为null,可以简化成这样:
@Override public int compare(IProduct product1, IProduct product2) throws ProductComparisonException { return Comparator.comparing( IProduct::getVintage, Comparator.nullsLast(Comparator.naturalOrder()) ).compare(product1, product2); }
额外提醒
如果vintage是自定义类型,记得确保该类型的compareTo方法本身是空安全的,或者你可以替换Comparator.naturalOrder()为自定义的比较逻辑。比如如果vintage是LocalDate这类自带空安全问题的类型,上面的写法完全适用;如果是自定义的枚举或实体类,只要它实现了Comparable接口,naturalOrder()就能正常工作。
内容的提问来源于stack exchange,提问作者Remo
相关产品推荐
相关产品推荐

