自JDK5.0以来,Java引入了自动装箱/取消装箱。这个技巧很简单而且很有帮助,但是当我开始测试包装器类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在Java是如何工作的。例如:
拳击
int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error
在尝试了不同的情况(short
、long
、float
、double
)后,编译器接受的唯一情况是做作运算符右侧值的类型为int
。当我查看integer.class
的源代码时,我发现它只实现了一个带有int
参数的构造函数。
所以我的结论是自动装箱的概念是基于在包装类中实现的构造函数。我想知道这个结论是真的还是有另一个概念被汽车拳击使用?
取消装箱
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
)。我想知道这个结论是真的还是自动解箱使用了另一个概念?
可以通过使用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文件,去掉了所有的语法糖(泛型类型、增强的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方法。
如果有疑问,请检查字节码:
Integer n = 42;
变成:
0: bipush 42
2: invokestatic #16 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
因此,实际上,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()
(同样,对于其他包装类型也是类似的)。这是真正的所有自动(联合国)拳击归结为。
您可以分别在JLS§5.1.7和JLS§5.1.8中阅读关于装箱和取消装箱转换的内容。
问题内容: 从JDK 5.0开始,自动装箱/拆箱是在Java中引入的,这种技巧很简单而且很有帮助,但是当我开始测试包装器类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在Java中的工作原理: Boxing 尝试不同的情况下后(),这是由编译器所接受的唯一情况是,当值的上做作运算符右侧的类型是int。当我查看源代码时,发现它仅实现一个带参数的构造函数。 因此,我的结论是,自动装箱的概念基于
请注意,对于某些数字,引用比较将产生正确的结果,因为Integer类维护了到之间的值的内部缓存(另请参阅TheLostMind的注释)。这就是为什么我在示例中使用的原因,也是为什么我特别询问取消装箱/装箱而不是比较结果的原因。
问题内容: 为什么第二段代码更快? 问题答案: 自动装箱使用,内部将Integer对象缓存为小整数(默认情况下为-128至127,但是最大值可以使用“ java.lang.Integer.IntegerCache.high”属性进行配置-请参见Integer.valueOf的源代码) ,因此与直接调用不同。因为在调用之前可以快速检查整数值的大小,所以直接调用要快一些(尽管如果您有很多小整数,它会使
本文向大家介绍自动装箱和拆箱?相关面试题,主要包含被问及自动装箱和拆箱?时的应答技巧和注意事项,需要的朋友参考一下 自动装箱是Java 编译器在基本数据类型和对应的对象包装类型之间做的一个转化。 比如:把int转化成 Integer,double转化成 Double,等等。反之就是自动拆箱。 原始类型: boolean,char,byte,short,int,long,float,double
问题内容: 以下代码进行编译(使用Java 8): 但是它是做什么的呢? 取消装箱: 或盒子: 那么它是比较两个对象(按引用)还是按值比较两个变量? 请注意,对于某些数字,引用比较将产生正确的结果,因为Integer类会维护一个介于to 之间的值的内部缓存(另请参见TheLostMind的注释)。这就是我在示例中使用的原因,也是为什么我特别询问拆箱/装箱而不是比较结果的原因。 问题答案: 它在JL