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

相关推荐
JavaGuide42 分钟前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613543 分钟前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源44 分钟前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
Java中文社群1 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心2 小时前
从零开始学Flink:数据源
java·大数据·后端·flink
间彧2 小时前
Spring Boot项目中如何自定义线程池
java
间彧2 小时前
Java线程池详解与实战指南
java
用户298698530142 小时前
Java 使用 Spire.PDF 将PDF文档转换为Word格式
java·后端
渣哥2 小时前
ConcurrentHashMap 1.7 vs 1.8:分段锁到 CAS+红黑树的演进与性能差异
java
间彧2 小时前
复用线程:原理详解与实战应用
java