Действительно ли это расширение против Autoboxing?

голоса
27

Я видел это в ответ на другой вопрос , ссылаясь на недостатки спецификации Java:

Есть несколько недостатков , и это тонкая тема. Проверьте это из:

public class methodOverloading{
     public static void hello(Integer x){
          System.out.println(Integer);
     }

     public static void hello(long x){
          System.out.println(long);
     }

     public static void main(String[] args){
         int i = 5;
         hello(i);
     }
}

Здесь «длинный» будет напечатан (не проверял это сам), потому что компилятор выбирает расширение над авто-бокса. Будьте осторожны при использовании авто-бокс или не использовать его на всех!

Мы уверены в том, что это на самом деле пример расширения вместо Autoboxing, или это что-то совсем другое?

На моем первоначальном сканировании, я согласился бы с утверждением , что вывод будет «долго» на основе iдекларируемых как примитив , а не объект. Однако, если вы изменили

hello(long x)

в

hello(Long x)

выход будет печатать «Integer»

Что происходит на самом деле здесь? Я ничего не знаю о компиляторов / интерпретаторов байт-кода для Java ...

Задан 07/08/2008 в 17:30
источник пользователем
На других языках...                            


3 ответов

голоса
13

В первом случае, у вас есть расширяющее преобразование происходит. Это может быть увидеть, когда runinng сервисной программы «javap» (входит в комплекте ж / JDK), на скомпилированном классе:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   i2l
   4:   invokestatic    #6; //Method hello:(J)V
   7:   return

}

Очевидно, что вы видите I2l, который мнемонические для расширяющегося Integer-To-Long инструкции байт - кода. Смотрите ссылку здесь .

А в другом случае, заменив «длинную х» с объектом «Long х» подпись, вы будете иметь этот код в основном методе:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   invokestatic    #7; //Method hello:(Ljava/lang/Integer;)V
   9:   return

}

Таким образом, вы видите, что компилятор создал команду Integer.valueOf (INT), боксировать примитив внутри обертки.

Ответил 07/08/2008 d 19:18
источник пользователем

голоса
4

Да, это, попробовать его в тесте. Вы увидите «длинные» напечатаны. Она расширяется, потому что Java будет выбрать, чтобы расширить Int в задолго до того, выбирает Autobox его к Integer, поэтому (длинный) метод привет выбран называться.

Edit: исходное сообщение на которую ссылается .

Далее Edit: Причина второго варианта печати Integer потому, что нет никакого «расширение» в большом примитивный, как вариант, поэтому он должен боксировать его, таким образом, Integer является единственным вариантом. Кроме того, Java будет только Autobox к первоначальному типу, так что это даст ошибку компиляции, если оставить привет (Long) и удалить привет (Integer).

Ответил 07/08/2008 d 17:36
источник пользователем

голоса
2

Еще одна интересная вещь с этим примером является метод перегрузки. Сочетание типа расширения и метода перегрузки работает только потому, что компилятор должен принять решение, какой метод выбрать. Рассмотрим следующий пример:

public static void hello(Collection x){
   System.out.println("Collection");
}

public static void hello(List x){
   System.out.println("List");
}

public static void main(String[] args){
   Collection col = new ArrayList();
   hello(col);
}

Он не использует тип времени выполнения, которое List, он использует тип времени компиляции, который является сбор и, таким образом, печатает «Коллекция».

Призываю Ваш читать Effective Java , который открыл мне глаз на некоторые угловых случаи JLS.

Ответил 07/08/2008 d 20:02
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more