Урок 12

Автоупаковка


1. Что такое автоупаковка и распаковка

Автоупаковка и распаковка это процесс преобразования примитивных типов в объектные и наоборот. Весь процесс выполняется автоматически средой выполнения Java (JRE). 

Пример 1. Автоупаковка и распаковка

public class AutoBoxDemo1 {
    public static void main(String[] args) {
        Integer iOb = 100; // autobox an int
        int i = iOb; // auto-unbox
        System.out.println(i + " " + iOb);  // displays 100 100
    }
}

Автоупаковка происходит при прямом присвоении примитива классу-обертке (с помощью оператора "="), либо при передаче примитива в параметры метода (типа «класса-обертки»).

Распаковка происходит при прямом присвоении классу-обертке примитива.

Компилятор использует метод valueOf() для упаковки, а методы intValue(), doubleValue() и т.д., для распаковки.

До Java 5 работа с классами обертками была более трудоемкой:

Пример 2. Работа с классами обертками до Java 5

public class AutoBoxDemo2 {
    public static void main(String[] args) {
        Integer y = new Integer(567); // make it
        int x = y.intValue(); // unwrap it
        x++; // use it
        y = new Integer(x); // re-wrap it
        System.out.println("y = " + y); // print it
    }
}

Пример 3. Работа с классами обертками начиная с Java 5

public class AutoBoxDemo3 {
    public static void main(String[] args) {
        Integer y = new Integer(567); // make it
        y++; // unwrap it, increment it, rewrap it
        System.out.println("y = " + y); // print it
    }
}

Автоупаковке в «классы-обертки» могут быть подвергнуты как переменные примитивных типов, так и литералы:

Integer iOb1 = 100;
int i = 200;
Integer iOb2 = i;

Автоупаковка переменных примитивных типов требует точного соответствия типа исходного примитива — типу «класса-обертки». Например, попытка автоупаковать переменную типа byte в Short, без предварительного явного приведения byte->short вызовет ошибку компиляции:

byte b = 4;
// Short s1 = b;
Short s2 = (short) b;

2. Объекты классов оболочек неизменяемы

Объекты классов оболочек неизменяемы (immutable). 

Рассмотрим следующий пример:

Integer y = 567;

Переменная y указывает на объект в памяти:

Объекты классов оболочек неизменяемы

Если мы попытаемся изменить y, у нас создастся еще один объект в памяти, на который теперь и будет указывать y:

Integer y = 567; 
y++; 

Объекты классов оболочек неизменяемы

Пример 4. Объекты классов оболочек неизменяемы

public class AutoBoxDemo4 {
    public static void main(String[] args) {
        Integer y = 567; // make a wrapper
        Integer x = y; // assign a second ref  var to THE wrapper
        // verify that they refer  to the same object
        System.out.println(y == x);

        y++; // unwrap, use, "rewrap"
        System.out.println(x + " " + y); // print values
        // verify that they refer to different objects
        System.out.println(y == x);
    }
}

3. Кэширование

Метод valueOf() не всегда создает новый объект. Он кэширует следующие значения:

  • Boolean, 
  • Byte,
  • Character от\u0000 до \u007f (7f это 127),
  • Short и Integer от-128 до 127.

Если передаваемое значение выходит за эти пределы, то новый объект создается, а если нет, то нет.

Если мы пишем new Integer(), то гарантированно создается новый объект.

Пример 5. Boxing, ==, и equals()

public class AutoBoxDemo5 {
    public static void main(String[] args) {
        Integer i1 = 23;
        Integer i2 = 23;
        System.out.println(i1 == i2);
        System.out.println(i1.equals(i2));

        Integer i3 = 2300;
        Integer i4 = 2300;
        System.out.println(i3 == i4);
        System.out.println(i3.equals(i4));
    }
}

4. Автоупаковка и методы

Пример 6. Использование автоупаковки при вызове метода

public class AutoBoxDemo6 {
    static int m(Integer v) {
        return v; // auto-unbox to int
    }

    public static void main(String[] args) {
        Integer iOb = m(100);
        System.out.println(iOb);
    }
}

5. Автоупаковка, распаковка в выражениях

Внутри выражения числовой объект автоматически распаковывается. Выходной результат выражения при необходимости упаковывается заново.

Пример 7. Использование автоупаковки, распаковки в выражениях

public class AutoBoxDemo7 {
    public static void main(String[] args) {
        Integer iOb1, iOb2;
        int i;

        iOb1 = 100;

        iOb2 = iOb1 + iOb1 / 3;
        System.out.println("iOb2 после выражения: " + iOb2);

        i = iOb1 + iOb1 / 3;
        System.out.println("i до выражения: " + i);
    }
}

C появлением автоупаковки/распаковки стало возможным применять объекты Boolean для управления в операторе if и других циклических конструкциях Java.

Пример 8. Автоупаковка, распаковка значений Boolean, Character

public class AutoBoxDemo8 {
    public static void main(String[] args) {
        Boolean b = true;

        if (b) {
            System.out.println("b is true");
        }

        Character ch = 'x'; 
        char ch2 = ch;

        System.out.println("ch2 is " + ch2);
    }
}


0 comments
Leave your comment: