9

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

 3 years ago
source link: https://minei.me/archives/422.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

boyizmen
2018-11-11
Java 

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

  1. Integer a = null;
  2. boolean flag = true;
  3. 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()方法,也就有了空指针异常。

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

  1. Integer a = null;
  2. boolean flag = true;
  3. 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的警告依旧存在。

这是一个非常隐蔽,也非常容易忽略和踩坑的一个地方,三目运算符的使用应该保证后面的值都是常量,或者统一类型,不然就会出现上面的情况。
更甚三目运算符本身提供的作用也不过是为了简化逻辑,在其中放入过多的逻辑判断也就违背了其初衷。

版权所有丨转载请注明出处:https://minei.me/archives/422.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK