下面测试代码运行后,会出现NullPointerException,一般人都会感觉奇怪,为什么会报NullPointerException。
@Test
public void test(){
Integer code = null;
// 这里会报NPE异常,原因;
// Integer 拆箱的问题, 0 是int类型,比较时code会自动拆箱,拆箱调用的是Integer里的intValue()方法,而此时code是null,自然就会报NPE异常
if (code == 0){
System.out.println("会报NEP异常");
}
}
原因分析:
通过对.class文件(javap -c xx.class)反汇编可以看到,Code序号4,调用了Integer.intValue()方法,为什么呢,这得从int和Integer的关系说起,Integer跟int比较时,会存在一个拆箱的过程,也就是把Integer转换成int,实际就是调用了Integer.intValue()方法,当执行null.intValue()方法自然就会出现NPE异常了。
// javap -c xx.class 后看到的反汇编代码
public void test();
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: aload_1
4: invokevirtual #7 // Method java/lang/Integer.intValue:()I
7: if_icmpne 18
10: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
13: ldc #9 // String ==============
15: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
18: return
PS:
Integer a = 1;这样声明一个Integer类型的a变量,就会把int类型的1自动装箱成Integer对象,用javap -c 命令会发现,底层实际就是调用了Integer.valueOf(int i)方法实现装箱。
// 实现装箱的方法,从这里也能看出Integer的缓存池是[-128 , 127]之间。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}