自动装箱/取消装箱在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

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

拳击

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
是对象还是基元类型,对吗?我认为编译器使用的是方法ode>Integer.intValue()要取消包装值的装箱,是否正确?@LouisWasserman非常感谢您的链接非常有用,它回答了我的问题。事实上,我是java初学者(我不懂字节码),所以当我开始阅读自动装箱的一章时,它只给出了一些自动装箱/取消装箱限制的例子,而不是所有规则,然后我试图分析所有的案例,并想确认我对这个概念的理解是否正确。@拳击是会发生的。正如我在回答中指出的那样,它归结为两个特定方法的调用;
valueOf()
intValue()
(分别)。感谢帮助:),我想我是那个愚蠢的人,问了一个我现在无法理解的解释(我应该更多地了解java)。谢谢。我觉得隐式装箱/拆箱很贵,从来没有真正推荐过。我想约书亚·布洛赫可能会这么说?那么现在可以接受使用隐式转换而不必显式调用
valueOf()
intValue()