Java三目运算中隐藏的自动拆装箱

 更新时间:2018年11月12日 08:25:10   作者:by Boyizmen  
这篇文章主要介绍了Java三目运算中隐藏的自动拆装箱,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

最近修改线上bug的时候排查了一个十分隐藏的bug,直接上代码:

Integer a = null;
boolean flag = true;
Integer b = flag ? a : 0;

乍一看是没什么毛病的,但是已运行就会发现报空指针,在idea里面也会警告可能有空指针,这是什么原因呢?

直接看字节码:

0: aconst_null
1: astore_1
2: iconst_1
3: istore_2
4: iload_2
5: ifeq     15
8: aload_1
9: invokevirtual #2       // Method java/lang/Integer.intValue:()I
12: goto     16
15: iconst_0
16: invokestatic #3      // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
19: astore_3
20: getstatic   #4      // Field java/lang/System.out:Ljava/io/PrintStream;
23: aload_3
24: invokevirtual #5      // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
27: return

可以看到字节码中调用了`Integer.valueOf()`方法,因为我们代码中一个值使用的是0(基本数据类型int),编译器就会进行自动拆装箱(成int),

虽然三目运算的后面逻辑不会执行,但是隐藏的自动拆装箱会执行`Integer.valueOf()`方法,也就有了空指针异常。

为了进一步验证存在自动拆装箱,把代码修改一下:

Integer a = null;
boolean flag = true;
Integer b = flag ? a : new Integer(0);

再看字节码:

0: aconst_null
1: astore_1
2: iconst_1
3: istore_2
4: iload_2
5: ifeq     12
8: aload_1
9: goto     20
12: new      #2      // class java/lang/Integer
15: dup
16: iconst_0
17: invokespecial #3      // Method java/lang/Integer."<init>":(I)V
20: astore_3
21: getstatic   #4      // Field java/lang/System.out:Ljava/io/PrintStream;
24: aload_3
25: invokevirtual #5      // Method java/io/PrintStream.println:(Ljava/lang/Object;)V

可以看到,由于重新创建了一个`Integer`对象,并没有基本类型的存在,也就不存在自动拆装箱,修改过后的代码也就不会有问题了,但是idea的警告依旧存在。

这是一个非常隐蔽,也非常容易忽略和踩坑的一个地方,三目运算符的使用应该保证后面的值都是常量,或者统一类型,不然就会出现上面的情况。

更甚三目运算符本身提供的作用也不过是为了简化逻辑,在其中放入过多的逻辑判断也就违背了其初衷。

总结

以上所述是小编给大家介绍的Java三目运算中隐藏的自动拆装箱,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

相关文章

  • java 判断二进制文件的方法

    java 判断二进制文件的方法

    这篇文章主要介绍了java 判断二进制文件的方法的相关资料,这里提供实例来实现判断文件是否问二进制文件,希望能帮助到大家,需要的朋友可以参考下
    2017-09-09
  • 浅谈spring注解之@profile

    浅谈spring注解之@profile

    这篇文章主要介绍了浅谈spring注解之@profile,@profile通过配置来改变参数,这里整理的详细的用法,有兴趣的可以了解一下
    2017-10-10
  • 详解SpringBoot如何优雅的进行前后端通信

    详解SpringBoot如何优雅的进行前后端通信

    现在的项目基本上都是前后端分离的项目,如何打通前后端,接收前端传过来的参数呢,下面小编就来和大家详细介绍一下SpringBoot如何优雅的进行前后端通信
    2024-03-03
  • SpringBoot整合Graylog做日志收集实现过程

    SpringBoot整合Graylog做日志收集实现过程

    这篇文章主要为大家介绍了SpringBoot整合Graylog做日志收集实现过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Java System.currentTimeMillis()时间的单位转换与计算方式案例详解

    Java System.currentTimeMillis()时间的单位转换与计算方式案例详解

    这篇文章主要介绍了Java System.currentTimeMillis()时间的单位转换与计算方式案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java 在Word中创建邮件合并模板并合并文本和图片的操作方法

    Java 在Word中创建邮件合并模板并合并文本和图片的操作方法

    通过Java程序展示如何来实现创建模板,并通过邮件合并功能来合并文本数据和图片数据的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-07-07
  • mysql+spring+mybatis实现数据库读写分离的代码配置

    mysql+spring+mybatis实现数据库读写分离的代码配置

    今天小编就为大家分享一篇关于mysql+spring+mybatis实现数据库读写分离的代码配置,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Java中的JSONObject使用方法和常用操作

    Java中的JSONObject使用方法和常用操作

    本文详细介绍了Java中JSONObject的使用方法,包括创建、基本操作、高级特性和错误处理,通过示例代码和解释,帮助开发者更好地理解和使用JSONObject来处理JSON数据,感兴趣的朋友一起看看吧
    2025-02-02
  • 在IntelliJ IDEA中多线程并发代码的调试方法详解

    在IntelliJ IDEA中多线程并发代码的调试方法详解

    这篇文章主要介绍了在IntelliJ IDEA中多线程并发代码的调试方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java中应用Stack进行算术运算的操作

    java中应用Stack进行算术运算的操作

    这篇文章主要介绍了java中应用Stack进行算术运算的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03

最新评论