从JDK 5.0开始,自动装箱/拆箱是在Java中引入的,这种技巧很简单而且很有帮助,但是当我开始测试包装器类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在Java中的工作原理:
Boxing
int intValue = 0; Integer intObject = intValue; byte byteValue = 0; intObject = byteValue; // ==> Error
尝试不同的情况下后(short,long,float,double),这是由编译器所接受的唯一情况是,当值的上做作运算符右侧的类型是int。当我查看源代码时,Integer.class发现它仅实现一个带int参数的构造函数。
short,long,float,double
Integer.class
int
因此,我的结论是,自动装箱的概念基于在包装类中实现的构造函数。我想知道这个结论是否正确,还是自动装箱使用了另一个概念?
Unboxing
Integer intObject = new Integer(0); byte byteValue = intObject; // ==> Error (the same Error with short) int intValue = intObject; double doubleValue = intObject;
我关于拆箱的结论是,包装器类提供了对象以相应类型(Integer==> int)包装的值,然后编译器使用转换原始类型的常规规则(byte=> short=> int=> long=> float=> double)。我想知道这个结论是否正确,还是自动拆箱使用了另一个概念?
Integer==> int
byte=> short=> int=> long=> float=> double
谢谢你的进阶:)
如有疑问,请检查字节码:
Integer n = 42;
变成:
0: bipush 42 2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: astore_1
因此,实际上,它valueOf()是与构造函数相对使用的(其他包装类也是如此)。这是有益的,因为它允许缓存,并且不会在每次装箱操作时强制创建新对象。
valueOf()
反之则如下:
int n = Integer.valueOf(42);
0: bipush 42 2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 5: invokevirtual #22 // Method java/lang/Integer.intValue:()I 8: istore_1
即intValue()使用(同样,它也与其他包装类型类似)。这实际上是所有自动装箱归结为。
intValue()
你可以分别在JLS§5.1.7和JLS§5.1.8中了解装箱和拆箱转换。