当前位置: 首页 > 知识库问答 >
问题:

自动装箱/取消装箱在Java是如何工作的?

党星鹏
2023-03-14

自JDK5.0以来,Java引入了自动装箱/取消装箱。这个技巧很简单而且很有帮助,但是当我开始测试包装器类和原始类型之间的不同转换时,我真的很困惑自动装箱的概念在Java是如何工作的。例如:

拳击

int intValue = 0;
Integer intObject = intValue;
byte byteValue = 0;
intObject = byteValue; // ==> Error

在尝试了不同的情况(shortlongfloatdouble)后,编译器接受的唯一情况是做作运算符右侧值的类型为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)。我想知道这个结论是真的还是自动解箱使用了另一个概念?

共有2个答案

欧旻
2023-03-14

可以通过使用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方法。

梁昊天
2023-03-14

如果有疑问,请检查字节码:

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