Как зайти в Даркнет?!
25th January, 01:11
94
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
1228
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
1029
0
Очень долго работает Update запрос Oracle
27th January, 09:58
969
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
959
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
995
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1782
0
период по дням
25th October, 10:44
4001
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3775
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4661
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4442
0
Помогите пожалуйста решить задачи
24th November, 23:53
6159
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4393
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4442
0
Метода Крамера С++
23rd October, 11:55
4356
0
помогите решить задачу на C++
22nd October, 17:31
4040
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4533
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2643
0
Это действительно расширение против автобоксинга?
Я видел это в ответе на другой вопрос, в отношении недостатков спецификации 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); } }Здесь "long" будет напечатан (не проверял его сам), потому что компилятор выбирает расширение вместо автоматического бокса. Будьте осторожны при использовании автоматического бокса или не используйте его вообще!
Уверены ли мы, что это на самом деле пример расширения вместо автобоксинга, или это что-то совсем другое?
На моем первоначальном сканировании я бы согласился с утверждением, что выход будет "long" на основе i , объявленного как примитив, а не объект. Однако, если вы изменились
hello(long x)
к
hello(Long x)
вывод будет печатать "Integer"
Что здесь на самом деле происходит? Я ничего не знаю о компиляторах/интерпретаторах байт-кода для java...
В первом случае происходит расширяющееся преобразование. Это можно увидеть при запуске утилиты "javap" (включенной w/ в 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 x" на сигнатуру объекта "Long x", вы получите этот код в основном методе:
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), чтобы поместить примитив в оболочку.
Да, это так, попробуйте это в тесте. Вы увидите "long" напечатанным. Он расширяется, потому что Java решит расширить int в long, прежде чем он решит автобокс его в целое число, поэтому метод hello(long) выбран для вызова.
Редактировать: ссылка на исходную запись .
Дальнейшее редактирование: причина, по которой второй вариант будет печатать целое число, заключается в том, что нет "widening" в большем примитиве в качестве опции, поэтому он MUST вставляет его, таким образом, Integer является единственным вариантом. Кроме того, java будет только autobox к исходному типу, поэтому он даст ошибку компилятора, если вы оставите hello(Long) и удалите hello(Integer).
Еще одна интересная вещь в этом примере-это перегрузка метода. Комбинация расширения типа и перегрузки метода работает только потому, что компилятор должен принять решение, какой метод выбрать. Рассмотрим следующий пример:
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);
}
Он не использует тип времени выполнения, который является списком, он использует тип времени компиляции, который является коллекцией, и таким образом печатает "Collection".
Я призываю вас прочитать эффективный Java, который открыл мне глаза на некоторые угловые случаи JLS.