问题复现
项目逻辑刚改了一大堆,上线,查看日志,忽然发现有一个NPE异常,我的乖乖,怎么还有NPE,这不可能啊。。。。
定位代码:
Integer itemMaxSale = NumberUtils.isParsable(itemDetail.getItemMonthSale())?Integer.parseInt(itemDetail.getItemMonthSale()):itemDetail.getItemTotalSale();
定位完毕,获取商品最大销售量,如果月销是数字就用数字,不是数字就用totalSale,乍一看,这某问题啊,一个为空,itemMaxSale 取另外一个值,即使getItemTotalSale为空,也是某问题滴呀,难道进入了Integer.parseInt(itemDetail.getItemMonthSale()) 这一行?
不可能,,绝对不可能。。。。。
public static void main(String[] args) {
MarketItemDetail itemDetail = new MarketItemDetail();
System.out.println(NumberUtils.isParsable(itemDetail.getItemMonthSale()));
System.out.println(itemDetail.getItemTotalSale());
}
false
null
所以没问题啊,这是肿么一回事?一定是某个环节有内鬼。。。。
解决
查看字节码:罪魁祸首:::32 invokevirtual #8 <java/lang/Integer.intValue>
0 new #2 <MarketItemDetail>
3 dup
4 invokespecial #3 <MarketItemDetail.<init>>
7 astore_1
8 aload_1
9 invokevirtual #4 <MarketItemDetail.getItemMonthSale>
12 invokestatic #5 <org/apache/commons/lang3/math/NumberUtils.isParsable>
15 ifeq 28 (+13)
18 aload_1
19 invokevirtual #4 <MarketItemDetail.getItemMonthSale>
22 invokestatic #6 <java/lang/Integer.parseInt>
25 goto 35 (+10)
28 aload_1
29 invokevirtual #7 <MarketItemDetail.getItemTotalSale>
32 invokevirtual #8 <java/lang/Integer.intValue>
35 invokestatic #9 <java/lang/Integer.valueOf>
38 astore_2
39 return
这32行是自动拆箱了呀,为啥类。。。为啥要拆箱。。。
直接小度度,发现有个三目运算符的语法规范。
这个规范一句话概括,冒号两边的数据类型要一致,不一致它会帮你一致,我手贱在冒号左边我用了 Integer.parseInt,
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
这返回值是一个int,是基本数据类型!!!!!!
看下面的valueOf,,返回值是Integer ,是包装类型!!!
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
我还想着反正valueOf底层调用的也是parseInt,我直接parseInt是不是很鸡贼,少让java转一层,,机智的一批~!!!!!!!
so,三目运算符左边是个int,右边也是是个int,不同的是itemDetail.getItemTotalSale()这是个Null,映射到class里面就是
32 invokevirtual #8 <java/lang/Integer.intValue>
所以NPE。。。。。。。。。。
立马改为:
Integer itemMaxSale = NumberUtils.isParsable(itemDetail.getItemMonthSale())?Integer.valueOf(itemDetail.getItemMonthSale()):itemDetail.getItemTotalSale();
运行不报错,不报错,不报错,不报错,不报错。。。。。。
解决2
又想到这些空值问题,还是用Optional吧,我为啥不用Optional????
Integer itemMaxSale = Optional.ofNullable(itemDetail.getItemMonthSale())
.filter(NumberUtils::isParsable)
.map(Integer::parseInt).orElse(itemDetail.getItemTotalSale());
和上面一样的运行效果,没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~