自动装箱/取消装箱在Java中是如何工作的?
自JDK5.0以来,Java中引入了自动装箱/取消装箱。这个技巧很简单,也很有用,但是当我开始测试包装类和基本类型之间的不同转换时,我真的很困惑自动装箱的概念在Java中是如何工作的。例如: 拳击自动装箱/取消装箱在Java中是如何工作的?,java,autoboxing,unboxing,Java,Autoboxing,Unboxing,自JDK5.0以来,Java中引入了自动装箱/取消装箱。这个技巧很简单,也很有用,但是当我开始测试包装类和基本类型之间的不同转换时,我真的很困惑自动装箱的概念在Java中是如何工作的。例如: 拳击 int intValue = 0; Integer intObject = intValue; byte byteValue = 0; intObject = byteValue; // ==> Error Integer intObject = new Integer(0); byte by
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
Integer intObject = new Integer(0);
byte byteValue = intObject; // ==> Error (the same Error with short)
int intValue = intObject;
double doubleValue = intObject;
在尝试了不同的情况(short
、long
、float
、double
)之后,编译器接受的唯一情况是矫揉造作运算符右侧的值类型为int
。
当我查看Integer.class
的源代码时,我发现它只实现了一个带有int
参数的构造函数
所以我的结论是,自动装箱的概念是基于包装器类中实现的构造函数。我想知道这个结论是真的还是自动装箱使用了另一个概念
拆箱
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
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 n = 42;
变成:
0: bipush 42
2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
因此,实际上,它的使用与构造函数相反(其他包装器类也是如此)。这是有益的,因为它允许缓存,并且不会强制在每个装箱操作上创建新对象
反之亦然:
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
i、 使用e(同样,它也类似于其他包装器类型)。这实际上是所有自动(非)装箱归结为
您可以分别在和中阅读有关装箱和取消装箱转换的信息。自动装箱和自动取消装箱
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
Integer intObject = new Integer(0);
byte byteValue = intObject; // ==> Error (the same Error with short)
int intValue = intObject;
double doubleValue = intObject;
自动装箱意味着当我们尝试将一个基本数据分配给一个对象类型时,它会自动将自己转换为对象类型。这个过程称为自动装箱。当一个对象类型转换为基本类型时,它称为取消装箱。试着从以下示例中理解它
class Demo{
public static void main(String args[]){
int x=100;
//Integer iob=x; //Illegal jdk1.4
Integer iob=Integer.valueOf(x); //Legal at JDK1.4 =>Boxing
Integer iob2=x; //Legal JDK1.5 - Autoboxing
System.out.println(iob2);
}
}
自动装箱的另一个例子
class Demo{
public static void main(String args[]){
Integer iob=new Integer(100);
int x;
x=iob; //Legal => auto unboxing
System.out.println(x);
}
}
自动拆箱示例
class Demo{
public static void main(String args[]){
Integer iob=new Integer(100);
int x=iob; //Auto unboxing ==>Assignment
}
}
谢谢..将以下代码作为自动取消装箱的示例:
System.out.println('b'+ new Integer(63));
下面是如何编译上述代码的详细信息:
步骤1:实例化对象整数63,然后自动取消绑定到int 63
new Integer(63)
步骤2:将字符“b”转换为数值,即98
步骤3:两个值相加:98+63
第4步:输出为161使用javac-XD printflat开关可以消除这种混淆,这在此类情况下非常有用。因此,要解开装箱和拆箱之谜,您可以编写如下简单程序:
import java.util.*;
public class Boxing{
public static void main(String[] args){
Double d1 = 10.123;
Float f1 = 12.12f;
Long l1 = 1234L;
Integer i1 = 55555;
Short s1 = 2345;
Byte b1 = 89;
double d2 = d1;
float f2 = f1;
long l2 = l1;
int i2 = i1;
short s2 = s1;
byte b2 = b1;
}
}
现在我们将上述文件编译为:
javac-XD printflat-d src/Boxing.java
此命令的输出是一个java文件,其中删除了所有语法sugar(泛型类型、增强的for循环以及在本例中的装箱取消装箱等)
import java.util.*;
public class Boxing {
public Boxing() {
super();
}
public static void main(String[] args) {
Double d1 = Double.valueOf(10.123);
Float f1 = Float.valueOf(12.12F);
Long l1 = Long.valueOf(1234L);
Integer i1 = Integer.valueOf(55555);
Short s1 = Short.valueOf(2345);
Byte b1 = Byte.valueOf(89);
double d2 = d1.doubleValue();
float f2 = f1.floatValue();
long l2 = l1.longValue();
int i2 = i1.intValue();
short s2 = s1.shortValue();
byte b2 = b1.byteValue();
}
}
java就是这样装箱的。使用valueOf和***Value方法。你读过关于自动装箱的java语言规范部分吗?
byte byteValue=intObject;
-你意识到这是一个错误,不管intObject
是对象还是基元类型,对吗?我认为编译器使用的是valueOf()
和intValue()
(分别)。感谢帮助:),我想我是那个愚蠢的人,问了一个我现在无法理解的解释(我应该更多地了解java)。谢谢。我觉得隐式装箱/拆箱很贵,从来没有真正推荐过。我想约书亚·布洛赫可能会这么说?那么现在可以接受使用隐式转换而不必显式调用valueOf()
和intValue()
?