诡异的NPE--三目运算自动类型转换

今天在项目中碰到一个诡异的空指针异常的问题,刚开始很不解,明明自己做了空判断,为什么还是出现了空指针呢?
最后排查出来的原因是:三目运算符的自动类型匹配机制。

现场

java.lang.NullPointerException: null

项目日志中突然出现NPE,这可是个禁忌,赶紧查代码:

ro.setStandardLevelId(positionByCode == null ? -1L : positionByCode.getStandardLevelId());

诶,这行代码怎么会报错?明明我已经做了空判断了啊!没办法,事实就是这样,debug解决。

眉目

设置值有问题,就先把被设置的值单独拿出来吧,使用IDE 自动生成变量之后,出来的类型像闪电一般击中了我:

long levelId = positionByCode == null ? -1L : positionByCode.getStandardLevelId();

出来的类型居然是原始类型long,并不是包装类型。所以这里应该是:后面的值是null,然后向下转型时,出现的空指针!!!
果然,如果像下面这么写,IDE 会直接提示:

原因找到了,解决当然很简单了。只是这种基础性的东西被忘记真的很不应该啊!!!

三目运算符回顾

  • 当后两个表达式有一个是常量表达式时,另外一个类型是T时,而常量表达式可以被T表示时,输出结果是T类型
  • 如果第二和第三个操作数在可以转换为数值类型时,会有以下几种情况:
    操作数其中一个是 byte 或 Byte 类型,而另一个是 short 或 Short 类型,那么这个表达式就是 short 类型
    操作数中的一个是类型 T (T 可以是 byte、short 或者是 char 类型),而另一个是 int 类型的常数,其可以用 T 类型来表示时,那么这个表达式就是 T 类型
    操作数中的一个是 Byte 类型,而另一个是 int 类型的常数,其可以用 byte 类型来表示,那么这个表达式就是 byte 类型
    操作数中的一个是 Short 类型,而另一个是 int 类型的常数,其可以用 short 类型来表示,那么这个表达式就是 short 类型
    操作数中的一个是 Character 类型,而另一个是 int 类型的常数,其可以用 char 类型来表示,那么这个表达式就是 char 类型
    否则,双目数值提升(binary numeric promotion)会被用于操作数的类型中,条件表达式的类型是第二个和第三个操作数提升后的类型。注意:双目数值提升时进行拆箱转换和值集转换(value set conversion)
原文地址:https://www.cnblogs.com/paxing/p/10619984.html