Java隐式雷系类型转换导致的NPE

最近接到一个需求,要将某个字段从int转成long,我一看这部很简单 卡卡全文搜索,替换,解决编译问题,直接mr,发版! 然后到了金丝雀的时候,突然同事说,你代码npe了,好多,快回滚qaq

看错误日志之后,发现出问题的代码大概是这一个样子的:

java 复制代码
    public static void Int2Long2() {
        Integer a = null;
        Long b = null;
        Long c = a != null && a > 0 ? a : b;
        System.out.println("int to long: " + c);
    }

原本a和b都是int型, 需求要求我将b转成long类型的,所以我直接修改了声明时的类型,然后顺手改了下面c的类型 一看没有编译问题,就直接不管了,但是这里有一个坑

如果一个对象编译器可以推导出是初始化为null,那么编译之后就是 Ojbect 类型,而非声明的类型 如果基本类型的包装类型之间存在不一致的场景,默认是会通过基本类型来转换

所以对于上面的代码,编译之后的是:

java 复制代码
  public static void Int2Long2();
    descriptor: ()V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: aconst_null
         1: astore_0
         2: aconst_null
         3: astore_1
         4: aload_0
         5: ifnull        23
         8: aload_0
         9: invokevirtual #11                 // Method java/lang/Integer.intValue:()I
        12: ifle          23
        15: aload_0
        16: invokevirtual #11                 // Method java/lang/Integer.intValue:()I
        19: i2l
        20: goto          27
        23: aload_1
        24: invokevirtual #8                  // Method java/lang/Long.longValue:()J
        27: invokestatic  #9                  // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
        30: astore_2
        31: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        34: aload_2
        35: invokedynamic #10,  0             // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/Long;)Ljava/lang/String;
        40: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: return
      LineNumberTable:
        line 30: 0
        line 31: 2
        line 32: 4
        line 33: 31
        line 34: 43
      StackMapTable: number_of_entries = 2
        frame_type = 253 /* append */
          offset_delta = 23
          locals = [ class java/lang/Integer, class java/lang/Long ]
        frame_type = 67 /* same_locals_1_stack_item */
          stack = [ long ]
}

或者说是:

java 复制代码
public static void Int2Long2() {
    Object var0 = null;
    Object var1 = null;
    Long var2 = var0 != null && var0 > 0 ? (long)var0 : var1;
    System.out.println("int to long: " + var2);
}

注意其中的 /Long.longValue:()J 因为存在 (long) 来转换,所以一定要后面的变量非null才可以,否者就是会npe 而这种一串逻辑中存在隐式的类型转换的场景,很可能就会因为校验不严谨而出问题,最好还是一个个判断转换。

相关推荐
xUxIAOrUIII2 分钟前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home5 分钟前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
醇氧7 分钟前
org.jetbrains.annotations的@Nullable 学习
java·开发语言·学习·intellij-idea
Java&Develop9 分钟前
Aes加密 GCM java
java·开发语言·python
JIngJaneIL40 分钟前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
专注VB编程开发20年1 小时前
C#全面超越JAVA,主要还是跨平台用的人少
java·c#·.net·跨平台
南_山无梅落1 小时前
9.Python3集合(set)增删改查和推导式
java·开发语言
爱笑的眼睛112 小时前
超越MSE与交叉熵:深度解析损失函数的动态本质与高阶设计
java·人工智能·python·ai
全靠bug跑2 小时前
Spring Cloud OpenFeign 实战三部曲:快速集成 · 连接池优化 · 客户端抽取
java·spring boot·openfeign