Как работает java auto boxing/unboxing?

Поскольку JDK 5.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). Я хочу знать, верен ли этот вывод или существует другая концепция, используемая автоматической распаковкой?

Спасибо за продвижение:)

Ответ 1

В случае сомнений проверьте байт-код:

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() (опять же, он аналогичен другим типам обертки). Это действительно все авто (un) бокс спускается до.

Вы можете прочитать о конверсиях в боксе и распаковке в JLS §5.1.7 и JLS §5.1.8, соответственно.

Ответ 2

Автоматический бокс и авто распаковка

Автоматический бокс означает, что когда мы пытаемся присвоить примитивные данные типу объекта, он автоматически преобразует себя в тип объекта. Этот процесс называется автоматическим боксированием.. и когда тип объекта преобразуется в примитивный тип, он называется unboxing... попытайтесь понять это из следующих примеров.

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

}

}

спасибо..

Ответ 3

Рассмотрим следующий код как пример автоматического un-бокса:

System.out.println('b'+ new Integer(63));

Здесь описывается, как скомпилирован приведенный выше код:

Шаг 1: Объектное целое 63 создается и затем АВТО-UNBOXED до int 63

new Integer(63)

Шаг 2: char 'b' преобразуется в числовое значение, то есть 98

Шаг 3: добавляются два значения: 98 + 63

Шаг 4: Вывод 161

Ответ 4

Эта путаница может быть устранена с помощью переключателя 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, в котором удалены все синтаксические символы (универсальные типы, расширенные для цикла и, в данном случае, бокс-распаковка и т.д.). Следующий вывод

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.