三元运算导致的NPE及Optional使用方法

问题复现

项目逻辑刚改了一大堆,上线,查看日志,忽然发现有一个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());

和上面一样的运行效果,没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~没问题,不报错 ~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值