Boxing and Unboxing in Java
装箱(Boxing) 和 拆箱(Unboxing)
Autoboxing 是指Java编译器在基本类型与其对应的对象包装类之间进行的自动转换。例如,将int转换为Integer,将double转换为Double,等等。如果转换方向相反,则称为Unboxing。
以下是最简单的自动装箱示例:
Character ch = 'a';
本节其余示例均使用泛型。若您尚未熟悉泛型的语法,请参阅泛型章节。
考虑以下代码:
List<Integer> ints = new ArrayList<>();
for (int i = 1; i < 50; i+=2) {
ints.add(i);
}
尽管你向 ints 中添加的是 int 值(原始类型)而非 Integer 对象,代码仍能编译通过。由于 ints 是 Integer 对象的列表而非 int 值的列表,你可能会疑惑为何 Java 编译器未在编译时报错。编译器之所以不报错,是因为它会将i转换为Integer对象,再将该对象加入ints列表。因此编译器会在运行时将原代码转换为以下形式:
List<Integer> ints = new ArrayList<>();
for (int i = 1; i < 50; i+=2) {
ints.add(Integer.valueOf(i));
}
将基本类型值(例如整型)转换为对应包装类Integer的对象称为自动装箱。当基本类型值满足以下条件时,Java编译器会应用自动装箱:
- 作为参数传递给一个方法,该方法期望接收对应包装类的对象。
- 赋值给一个对应包装类的变量。
考虑以下方法:
public static int sumEven(List<Integer> ints) {
int sum = 0;
for (Integer i: ints) {
if (i % 2 == 0) {
sum+=i;
}
}
return sum;
}
由于取余运算符(%)和单目加运算符(+=)不适用于Integer bjects,您可能会疑惑Java编译器为何能无误编译该方法。编译器之所以不报错,是因为它会在运行时调用intValue()方法将Integer转换为int类型:
public static int sumEven(List<Integer> ints) {
int sum = 0;
for (Integer i : ints) {
if (i.intValue() % 2 == 0) {
sum += i.intValue();
}
}
return sum;
}
将包装类型Integer的对象转换为其对应的原始类型(int)值称为unboxing(拆箱)。当包装类的对象满足以下条件时,Java编译器会执行拆箱操作:
- 作为参数传递给一个方法,该方法期望接收对应基本数据类型的值。
- 赋值给对应基本类型的变量。
Unboxing 示例展示了其工作原理:
public class Unboxing {
public static void main(String[] args) {
Integer i = Integer.valueOf(-8);
// 1. Unboxing through method invocation
int absVal = absoluteValue(i);
IO.println("absolute value of " + i + " = " + absVal);
List<Double> doubles = new ArrayList<>();
doubles.add(3.1416); // Π is autoboxed through method invocation
// 2. Unboxing through assignment
double pi = doubles.get(0);
IO.println("pi = " + pi);
}
public static int absoluteValue(int i){
return i < 0 ? -i : i;
}
}
程序的输出如下:
absolute value of -8 = 8
pi = 3.1416
自动装箱和拆箱功能使开发人员能够编写更简洁的代码,从而更易于阅读。下表列出了基本类型及其对应的包装类,这些包装类被Java编译器用于自动装箱和拆箱操作:
| 基本类型 | 包装类 |
|---|---|
| boolean | Boolean |
| byte | Byte |
| char | Character |
| float | Float |
| int | Integer |
| long | Long |
| short | Short |
| double | Double |