Java拆箱/装箱原理

java中原始数据类型

byte     => Byte
short    => Short 
chart    => Character
int      => Integer
float    => Float
long     => Long
double   => Double
boolean  => Boolean

什么是自动拆箱、装箱

自动装箱就是自动将原始数据类型转换为对应的对象类型(编译器编译时调用valueOf将原始类型转换为对象)
自动拆箱就是自动将对象类型转换为原始数据类型(编译器编译时调用类似于intValue()、doubleValue()方法将对象转换为原始值)

// 自动装箱
Integer i = 1;
// 自动拆箱
int j = i;

自动拆箱、装箱的时机

赋值时

// 自动装箱
Integer i = 1;
// 自动拆箱
int j = i;

方法调用传值时

public void test(Integer i) {
    ...
}
test(1);

自动拆箱、装箱的弊端

自动拆箱、装箱看似简单方便(用着也确实方便),但是却隐藏着一些弊端

影响性能

在数据量小的时候可能没有太大的影响,但是随着数据量的增多就会额外的创建许多无意义的对象,以及数据转换的过程

Integer sum = 0;
for(int i = 0; i < 100000; i++) {
    sum += i;
}

因为sum是Integer对象,不支持 += 操作,所以循环中会进行类似如下的自动的拆箱再装箱的过程:

sum = sum.intValue() + i;
sum = Integer.valueOf(sum);

NullPointerException

Integer a = null;
int b = a;

上面的代码就会抛出空指针异常

== 判断问题(缓存问题)

这个在之前的文章中有介绍《Long == Long 有趣的现象》

重载与自动拆箱、装箱

当重载遇上自动装箱时,情况会比较有些复杂,可能会让人产生有些困惑。在1.5之前,value(int)和value(Integer)是完全不相同的方法,开发者不会因为传入是int还是Integer调用哪个方法困惑,但是由于自动装箱和拆箱的引入,处理重载方法时稍微有点复杂。一个典型的例子就是ArrayList的remove方法,它有remove(index)和remove(Object)两种重载,我们可能会有一点小小的困惑,其实这种困惑是可以验证并解开的,当出现这种情况时,不会发生自动装箱操作。

// demo1
public static void test1(int i) {
    System.out.println("int");
}

public static void test1(Integer i) {
    System.out.println("integer");
}

test1(1);
test1(Integer.valueOf(1));
输出结果为:
int
integer
// demo2
public static void test1(int i) {
    System.out.println("int");
}

//public static void test1(Integer i) {
//    System.out.println("integer");
//}

test1(1);
test1(Integer.valueOf(1));
输出结果为:
int
int
点赞