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

相关推荐
rannn_1118 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
IKUN家族10 小时前
Spring IoC&DI
java·spring·rpc
山荷枝11 小时前
03-框架--Spring
java·后端·spring
ChaHae-In11 小时前
SpringBoot统一功能处理
java·spring boot·后端
coder!mq12 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding12 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
心平气和量大福大12 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
9523613 小时前
Spring-cloud配置中心
java·spring·spring cloud·微服务
ydd10010013 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
真上帝的左手14 小时前
10. 软件设计&架构-Spring Security 7 整合CAS SSO 单点登录
java·spring·架构·sso