一、什么是自动装箱和拆箱
自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。 因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。
例子:
public static void main2(String[] args) {
Integer a = 2; //自动装箱, 语法糖
int b = a; //自动拆箱,语法糖
}
二、自动拆箱引起的空指针异常
自动拆箱,当包装对象为null时,会引起npe异常,例子:
public static void main2(String[] args) {
Integer a = null;
int b = a;
}
报错:
Exception in thread "main" java.lang.NullPointerException
at com.example.teasure.doamin.TestOpenNpe.main(TestOpenNpe.java:11)
三、原因
反编译上述代码,如下:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: iconst_2
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: aload_1
6: invokevirtual #3 // Method java/lang/Integer.intValue:()I
9: istore_2
10: return
LineNumberTable:
line 10: 0
line 11: 5
line 12: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
5 6 1 a Ljava/lang/Integer;
10 1 2 b I
MethodParameters:
Name Flags
args
#1可以看出,自动装箱其实是调用了包装类型的valueOf()函数。
#6可以看出,自动装箱其实是调用了包装类型对象的xxxValue()函数。
实际执行代码如下:
public static void main(String[] args) {
Integer a = null; //自动装箱, 语法糖
Integer a = Integer.valueOf(null); //实际执行
int b = a; //自动拆箱,语法糖
int b = a.intValue(); //实际执行
}
对照代码,如果a为null的话,那么在调用intValue方法时便会抛出NullPointerException。
所以,本质上来讲,所谓的自动拆箱和装箱只不过是Java提供的语法糖而已。
四、引申
函数中入参与出参的拆箱同理,以下代码皆会引起npe异常
public static Integer getA() {
return null;
}
public static void setA(int a) {
return;
}
public static void main1(String[] args) {
int a = getA(); //npe
Integer b = null;
setA(b); //npe
}