当前位置: 首页 > 编程笔记 >

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

万喜
2023-03-14
本文向大家介绍Java三目运算中隐藏的自动拆装箱,包括了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三目运算中隐藏的自动拆装箱,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

 类似资料:
  • 问题内容: 仅仅花了几个小时调试以下代码: 上面产生了一个NullPointerException。以下代码没有: 唯一的区别是用Integer.valueOf()包装-1。我敢肯定,一旦有人解释了为什么这段代码的行为方式如此,我就会打我的额头。但是有人可以向我解释为什么这段代码的行为方式:)吗? -编辑 再次考虑,我怀疑NPE来自返回null的rsrqs.get(),我认为Java在将其装箱回I

  • --编辑 再考虑一下,我怀疑NPE来自返回null的rsrqs.get(),我认为java试图在装箱返回整数之前将其解框为int。integer.valueOf()强制Java执行unbox-box步骤。故事的寓意;不要只是忽略Eclipse中的那些拳击警告;)

  • 问题内容: 前几天,我因三元运算符中意外的类型转换而遇到了一个非常奇怪的问题。鉴于此(无用的示例性)功能: 我期望编译后以下两个代码段完全相同: 与 。 事实证明,如果是,则-statement可以正常工作,而第二个代码段中的三元运算则抛出a 。似乎三元运算已决定将这两种选择都强制转换为类型,然后再将结果自动装箱为!?!。实际上,如果我将显式转换为,则该异常消失。换一种说法: 与以下内容不同: 。

  • 问题内容: 我想要一个不会在单击时自动隐藏的MenuItem(更具体地说是CheckMenuItem)。我知道CustomMenuItem具有此功能,但它应该是CheckMenuItem。 问题答案: 在构造函数中使用CustomMenuItem,setHideOnClick和CheckBox。 编辑: 我只是注意到JavaFX 8u40中将其弄乱了。菜单项的文本颜色与背景颜色相同,因此看不到任何

  • 本文向大家介绍自动装箱和拆箱?相关面试题,主要包含被问及自动装箱和拆箱?时的应答技巧和注意事项,需要的朋友参考一下 自动装箱是Java 编译器在基本数据类型和对应的对象包装类型之间做的一个转化。 比如:把int转化成 Integer,double转化成 Double,等等。反之就是自动拆箱。 原始类型: boolean,char,byte,short,int,long,float,double 

  • 问题内容: 从JDK 5.0开始,自动装箱/拆箱是在Java中引入的,这种技巧很简单而且很有帮助,但是当我开始测试包装器类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在Java中的工作原理: Boxing 尝试不同的情况下后(),这是由编译器所接受的唯一情况是,当值的上做作运算符右侧的类型是int。当我查看源代码时,发现它仅实现一个带参数的构造函数。 因此,我的结论是,自动装箱的概念基于