问题描述
自 JDK 5.0 起,Java 中引入了自动装箱/拆箱.这个技巧很简单而且很有帮助,但是当我开始测试包装类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在 Java 中是如何工作的.例如:
Since JDK 5.0, auto boxing/unboxing was introduced in Java. The trick is simple and helpful, but when I started testing different conversions between wrapper classes and primitive types, I get really confused how the concept of auto boxing works in Java. For example:
拳击
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
尝试不同的情况(short
、long
、float
、double
)后,唯一的情况是编译器接受的是当做作运算符右边的值的类型为int
时.当我查看 Integer.class
的源代码时,我发现它只实现了一个带有 int
参数的构造函数.
After trying different cases (short
, long
, float
, double
), the only case which is accepted by the compiler is when the type of the value on the right of affectation operator is int
.When I looked inside the source of Integer.class
I found that it implements only one constructor with int
parameter.
所以我的结论是自动装箱的概念是基于在包装类中实现的构造函数.我想知道这个结论是真的还是自动装箱使用的另一个概念?
So my conclusion is that the concept of auto boxing is based on constructor implemented in the wrapper class. I want to know if this conclusion is true or there is another concept used by auto boxing?
拆箱
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
).我想知道这个结论是否正确,或者自动拆箱使用了另一个概念?
My conclusion about unboxing is that the wrapper class gives the value wrapped by the object in the corresponding type (Integer
==> int
), then the compiler use the usual rules of converting primitive types (byte
=> short
=> int
=> long
=> float
=> double
).I want to know if this conclusion is true or there is another concept used by auto unboxing?
推荐答案
如有疑问,请检查字节码:
When in doubt, check the bytecode:
Integer n = 42;
变成:
0: bipush 42
2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
所以实际上,valueOf()
与构造函数相反(其他包装类也是如此).这是有益的,因为它允许缓存,并且不会在每次装箱操作时强制创建新对象.
So in actuality, valueOf()
is used as opposed to the constructor (and the same goes for the other wrapper classes). This is beneficial since it allows for caching, and doesn't force the creation of a new object on each boxing operation.
反之如下:
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()
被使用(同样,对于其他包装器类型也是类似的).这实际上是所有自动(取消)拳击归结为.
i.e. intValue()
is used (again, it's analogous for the other wrapper types as well). This is really all auto(un)boxing boils down to.
您可以在 阅读有关装箱和拆箱转换的信息JLS §5.1.7 和 JLS §5.1.8,分别.
You can read about boxing and unboxing conversions in JLS §5.1.7 and JLS §5.1.8, respectively.
这篇关于Java 中的自动装箱/拆箱是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!