装箱和拆箱
装箱-将基本数据类型转换为包装器类型;拆箱-包装器类型转换为基本数据类型。
基本类型 | 包装类型 |
---|---|
int | Integer |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
为什么需要装箱,拆箱
Java包含基本数据类型和引用数据类型两种数据类型,在一些特殊情况下,如使用java.util.Collection类型时,我们想要创建一个基本类型的集合,但Collection的实现并不支持基本类型集合,所以只能创建对象的集合。如下:
ArrayList al = new ArrayList(); // not supported
ArrayList al = new ArrayList(); // supported
al.add(45); //auto Boxing
所以装箱可以帮助我们处理一些特殊的只能使用引用类型的场合。
自动装箱和自动拆箱
自动装箱是JDK5后,Java编译器在基础类型及其对应的包装器类之间进行的自动转换。
在JDK5以前,生成一个Character对象需要这样做
Character ch = new Character('a');
在JDK5之后,因为有了自动装箱,所以只需要这样
Character ch = 'a';
这个过程中会自动根据char创建对应Character对象,这就是自动装箱。反之自动拆箱的效果如下:
Integer i = 10; //装箱
int n = i; //拆箱
一些自动装箱和自动拆箱产生的问题
1.如下代码输出结果是什么?
public class Main {
public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2);
System.out.println(i3==i4);
}
}
输出结果:
true
false
原因:
自动装箱实际上使用的包装类中的valueOf方法,如:Integer.valueOf(),其代码如下:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用,否则创建一个新的Integer对象,所以输出结果如上所示。感兴趣可以继续研究IntegerCache类。
Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。
Boolean值因为只有true和false两种,所以始终不重新创建对象
Double、Float由于区间是无限的所以不存在缓存,其valueOf方法会重新创建对象,无论值是多少,输出都为false
2.如下代码输出结果是什么?
public class Main {
public static void main(String[] args) {
int a = 7;
doSomething(a);
}
private static void doSomething(double value){
System.out.println("double = " + value);
}
private static void doSomething(Integer value){
System.out.println("Integer = " + value);
}
}
输出结果:
double = 7
原因:
对于int类型来说,既可以通过隐式强制转换转换为double,也可以通过自动装箱转换为Integer,但自动装箱是JDK5之后才加入的功能,所以这里的结果和JDK5前保持一致,从而优先隐式强制转换转
参考
Why do we use autoboxing and unboxing in Java?
深入剖析Java中的装箱和拆箱
Autoboxing and Unboxing