Java三目运算中隐藏的自动拆装箱
作者:by Boyizmen 发布时间:2023-11-29 10:47:10
最近修改线上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三目运算中隐藏的自动拆装箱,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
来源:https://minei.me/archives/422.html


猜你喜欢
- 在讲述这个模式之前,我们先看一个案例:游戏回档游戏的某个场景,一游戏角色有生命力、攻击力、防御力等数据,在打Boss前和后会不一样,我们允许
- 方法调用在程序运行时,进行方法调用是最普遍,最频繁的操作方法调用不等于方法执行:方法调用阶段唯一的任务就是确定被调用的方法版本,即调用哪一个
- 位操作符是对数据按二进制位进行运算的操作符。位操作是其他很多语言都支持的操作,如C、C++和Java等,C#也不例外支持位操作。注意位操作支
- timer和timertask是jdk自带的定时任务实现,无需导入第三方jar包来完成1、指定多久之后执行此任务,注意:只会执行一次publ
- 前言随着使用 Spring 进行开发的个人和企业越来越多,Spring 也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring
- Spring-boot目的Spring是为了解决企业应用开发的复杂性而创建的,简化开发Spring如何简化开发1.基于POJO的轻量级和最小
- 本文实例为大家分享了java连接SQL Server数据库的具体代码,供大家参考,具体内容如下操作系统:windows 10 64位java
- 本文实例讲述了Android播放assets文件里视频文件相关问题。分享给大家供大家参考,具体如下:今天做了一个功能,就是播放项目工程里面的
- 前言解放双手!推荐一款阿里开源的低代码工具,YYDS!之前分享过一些低代码相关的文章,发现大家还是比较感兴趣的。之前在我印象中低代码就是通过
- 前言对于数组遍历,基本上每个开发者都写过,遍历本身没什么好说的,但是当我们在遍历的过程中,有一些复杂的业务逻辑时,将会发现代码的层级会逐渐加
- 1、什么是ThreadLocal变量ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thr
- Unity是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的
- 前言Spring常见的创建bean实例的方式有:1.通过bean的class属性创建实例 无参构造器带参构造器2.工厂方法静态工厂
- 工作中因业务需求,将数据库中的树状结构的数据根据父节点获取所有的子节点实现思路1.获取整个数据的list集合数据2.将数据分组,java8
- 如下所示本来 bookService的引用一直是null。导致每次测试都报空指针异常。然后现在继承相应的 ApplicationTests类
- MVP(Model-View-Presenter) 是总所周知MVC模式的一个演变,他们的主要目的都是划分模块职责,降低模块耦合,易测试,提
- 一、介绍Android的大部分自定义软键盘主要是通过android自带控件KeyboardView实现的。那么,有没有其他简单易上手的方法来
- 对大部分系统来说都需要权限管理来决定不同用户可以看到哪些内容,那么如何在Spring MVC中实现权限验证呢?当然我们可以继续使用servl
- 前言本篇文章 中写到的是 flutter 调用了Android 原生的 TextView 案例添加原生组件的流程基本上可以描述为:1 and
- 前面一篇文章已经写了如何搭建一个单机版Redis服务, 那么我们应该怎么在现有的系统中集成进来呢? 由于笔者使用的编程语言是Java, 所以