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

相关推荐
不才不才不不才3 分钟前
Spring AI 实战:聊天、提示词、记忆三件套
java·人工智能·spring·ai
一 乐2 小时前
家政服务管理系统|基于springboot + vue家政服务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·家政服务管理系统
碳基硅坊3 小时前
Spring AI:把大模型接进 Spring 应用
java·人工智能·spring ai
黄毛火烧雪下3 小时前
Java 核心知识点总结(一)
java·开发语言
技术小结-李爽3 小时前
【工具】Maven的下载、安装、使用
java·maven
极创信息3 小时前
Linux挖矿病毒深度清理实战教程,从进程隐藏、Rootkit驻留到彻底根除
java·大数据·linux·运维·安全·tomcat·健康医疗
努力成为AK大王4 小时前
并发编程的核心挑战、优化方案与核心知识点总结
java·开发语言·数据库
云烟成雨TD4 小时前
Agent Scope Java 2.x 系列【10】技能(Skill)
java·人工智能·agent
摇滚侠4 小时前
SpringMVC 入门到实战 DispatcherServlet 源码解读 92-95
java·后端·spring·maven·intellij-idea
键盘歌唱家4 小时前
Spring AI 入门分享:它和“直接调 API“到底差在哪
java·人工智能·spring