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 而这种一串逻辑中存在隐式的类型转换的场景,很可能就会因为校验不严谨而出问题,最好还是一个个判断转换。

相关推荐
天天扭码12 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶12 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺17 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
小曲程序24 分钟前
vue3 封装request请求
java·前端·typescript·vue
陈王卜42 分钟前
django+boostrap实现发布博客权限控制
java·前端·django
小码的头发丝、42 分钟前
Spring Boot 注解
java·spring boot
java亮小白19971 小时前
Spring循环依赖如何解决的?
java·后端·spring
飞滕人生TYF1 小时前
java Queue 详解
java·队列
武子康1 小时前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康1 小时前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql