Java装箱(Boxing Conversion)和拆箱(Unboxing Conversion)是一种类型转换。Java语言支持两种数据类型。一种是基本数据类型(Primitive Data Type),例如:int或者double;另一种是引用类型(Reference),例如:List类对象的引用。在Java程序中,基本数据类型的使用是很方便的,但是,因为基本数据类型和泛型编程不兼容(例如,无法使用List
在最新Java 13版本中,装箱和拆箱支持所有八种基本数据类型。
装箱(Boxing) | 拆箱(Unboxing) |
---|---|
boolean -> Boolean | Boolean -> boolean |
byte -> Byte | Byte -> byte |
short -> Short | Short -> short |
char -> Character | Character -> char |
int -> Integer | Integer -> int |
long -> Long | Long -> long |
float -> Float | Float -> float |
double -> Double | Double -> double |
null -> null |
将null->null也纳入装箱过程是有必要的。因为,在条件表达式(?:)中也会应用装箱转换,并进行相应的计算。
装箱和拆箱的内容并不复杂,实现起来也不难。下面的例子展示了一个装箱和拆箱的过程。装箱过程是将整形数值10装箱成一个Integer类的对象;而拆箱的过程是将这个Integer的对象拆成一个int基本数据类型。
public class BoxingExample {
public static void main(String[] args) {
Integer i = 10; // 装箱
int j = i; // 拆箱
}
}
从OpenJDK的实现来看,使用javap反汇编编译出的BoxingExample.class文件可知,上述装箱的过程实际上是调用了Integer.valueOf()函数,而拆箱的过程则是调用了Integer.intValue()函数。读者可以使用这种方法查看其他基本数据类型的装箱和拆箱过程。值得注意的是,这只是OpenJDK的实现方式。OpenJDK的其他版本或者其他JDK的实现可能会不同。
Compiled from "BoxingExample.java"
public class BoxingExample {
public BoxingExample();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 10
2: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: aload_1
7: invokevirtual #3 // Method java/lang/Integer.intValue:()I
10: istore_2
11: return
}
对于封装过程的实现,Java语言并没有更多详细的描述或者限制,各JDK软件可根据自身情况选择实现方法。下面我们简单的阅读一下OpenJDK 的实现内容。在Integer.valueOf()函数中,当输入的数值在IntegerCache.low和IntegerCache.high之间时,返回保存在IntegerCache中的对象;否则,创建一个新的Integer类的对象。在默认情况下,IntegerCache.low为-128,IntegerCache.high为127。但是这些值或者Integer::valueOf()函数的实现可能随着版本的变化而变化。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
本章介绍了Java的封箱转换和拆箱转换的概念。封箱转换和拆箱转换是一种类型转换,它在基本数据类型和对应的类的对象之间转换。封箱和拆箱的引入是为了解决基本数据类型与引用类型之间的兼容性问题。这种解决方案并不完美,所以,小水滴强烈建议,在Java程序设计过程中,尽量避免在类或者函数的接口处使用基本数据类型,建议使用对应的类。虽然使用引用类型会带来额外的开销,但是,这些开销是微乎其微的,基本可以忽略。
注册用户登陆后可留言