Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Что в приоритете: автоупаковка или автораспаковка?

#java #autoboxing #unboxing


public class Test {
    public static void main(String[] args) {
        Integer t = 1;
        int s = 1;
        System.out.println(s != t);  // (*)
    }
}


Вопрос: что делает компилятор со строкой (*)? Не понимаю, то ли распаковывает t,
то ли упаковывает s...
Мудрый человек, пишет что здесь идёт "autoboxing", но с ним мне не связаться и я
не знаю почему он так пишет.
Могу предположить только, что раз в сравнении у нас нашёлся Object some_obj, коим
является Integer t, то идёт сравнение по ссылкам, и int s автоупаковывается.
Из результатов программы: t==s -- правда. Не знаю почему так... Вроде потому, что
есть какой-то метод, который для Integer, String и подобных им приводит объект к некоторому
виду, заменяя ссылку на такой же по натуре объект, чтобы == работало. К примеру две
"разных" строки, например: "Hello" и "Hello" после вызова этого метода в сравнении
== дают true. 

Итого: очень хочу увидеть какое-то документальное объяснение происходящего, что к
чему приводится, и почему результат строки (*) есть false, что в принципе значит: t
и s равны. Но в каком понимании они равны? Ссылок, чисел?... Байт-код мне не помог,
там не понять как проходит это сравнение.
    


Ответы

Ответ 1



Происходит распаковывание t (то есть преобразование из Integer в int) с последующим обычным сравнением примитивов (то есть значений типа int). Чтобы понять почему так происходит обратимся к спецификации Java. Описание оператора == и !=, JLS 15.21.1: If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2). Если операнды оператора сравнения оба имеют числовой тип, или один из операндов является числовым типом, а второй может быть преобразован в числовой тип, то операнды подвергаются binary numeric promotion. В случае сравнения int и Integer операнд типа int является примитивным типом, а операнд типа Integer может быть преобразован в числовой тип. В принципе не важно, как переводится binary numeric promotion, важно лишь что при этом выполняются действия описанные в соответствующем разделе JLS 5.6.2: If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8). Если один из операндов является ссылочным типом, то происходит распаковывание. В нашем случае распаковывается Integer и получается int. Далее обычным способом сравниваются два примитива (значения типа int).

Ответ 2



Легко проверяется экспериментально. Через использование кэша: https://ideone.com/sEhpKz import java.util.*; import java.lang.*; import java.io.*; class Ideone { public static void main (String[] args) throws java.lang.Exception { Integer a1 = 1, a1024 = 1024, b1 = 1, b1024 = 1024; if (a1 != b1 || a1024 == b1024) { System.out.println("Can't detect :("); } else if (a1024 == 1024 && b1024 == 1024) { System.out.println("Unboxing"); } else if (a1 == 1 && b1 == 1) { System.out.println("Boxing"); } else { System.out.println("Boxing without cache o_O"); } } } Через исключение при unboxing'е null'а: https://ideone.com/ltbefI import java.util.*; import java.lang.*; import java.io.*; class Ideone { public static void main (String[] args) throws java.lang.Exception { Integer a = null; try { boolean ignored = a == 1; } catch (NullPointerException ex) { System.out.println("Unboxing"); return; } System.out.println("Boxing"); } } В обоих случаях выводится: Unboxing

Комментариев нет:

Отправить комментарий