Почему "короткая тридцать = 3 * 10" является правовым заданием?
Если short
автоматически повышается до int
в арифметических операциях, то почему:
short thirty = 10 * 3;
Юридическое назначение на short
переменная thirty
?
В свою очередь это:
short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
так же как и это:
int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
не компилируется, потому что назначение int
значение для short
не допускается без кастинга, как ожидалось.
Что-то особенное происходит с числовыми литералами?
3 ответа
Потому что компилятор заменяет 10*3
с 30 на самом времени компиляции. Итак, эффективно: short thirty = 10 * 3
рассчитывается во время компиляции.
Попробуйте изменить ten
а также three
в final short
(заставляя их компилировать постоянные времени) и посмотрим, что произойдет:P
Изучите байт-код, используя javap -v
для обеих версий (10*3
а также final short
). Вы сможете увидеть, что есть небольшая разница.
Итак, вот разница в байтовом коде для разных случаев.
Случай 1:
Java-код: main() { short s = 10*3; }
Байт-код:
stack=1, locals=2, args_size=1
0: bipush 30 // directly push 30 into "s"
2: istore_1
3: return
Дело -2:
public static void main(String arf[]) {
final short s1= 10;
final short s2 = 3;
short s = s1*s2;
}
Байт-код:
stack=1, locals=4, args_size=1
0: bipush 10
2: istore_1
3: iconst_3
4: istore_2
5: bipush 30 // AGAIN, push 30 directly into "s"
7: istore_3
8: return
Дело -3:
public static void main(String arf[]) throws Exception {
short s1= 10;
short s2 = 3;
int s = s1*s2;
}
Байт-код:
stack=2, locals=4, args_size=1
0: bipush 10 // push constant 10
2: istore_1
3: iconst_3 // use constant 3
4: istore_2
5: iload_1
6: iload_2
7: imul
8: istore_3
9: return
В приведенном выше случае 10
а также 3
взяты из локальных переменных s1
а также s2
Да, что-то особенное происходит с буквальным падежом: 10 * 3
будет оцениваться во время компиляции. Так что вам не нужно явное (short)
преобразование для умноженных литералов.
ten * three
не оценивается во время компиляции, поэтому требует явного преобразования.
Было бы другое дело, если бы ten
а также three
были отмечены final
,
Следующий ответ добавляет раздел JLS и некоторые подробности об этом поведении.
Согласно JLS §15.2 - Формы выражений
Некоторые выражения имеют значение, которое может быть определено во время компиляции. Это постоянные выражения (§15.28).