Почему «короткое тридцать = 3 * 10» - это юридическое задание?

103

Если 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значения a shortне допускается без ожидаемого приведения.

Что-то особенное происходит с числовыми литералами?

Потолок Геккон
источник
23
short thirty = 10 * 3;скорее всего заменяется short thirty = 30;компилятором, который тогда является допустимым оператором. (Хотя мне придется поискать соответствующий раздел JLS).
Thomas
Компилятор вычисляет 10 * 3и инициализирует переменную с результатом. В вашем нерабочем примере вычисление происходит во время выполнения, когда JVM выполняет короткий.
Феликс
Я думаю, что это дубликат stackoverflow.com/questions/30346587/java-char-to-byte-casting или stackoverflow.com/questions/9379983/… . Однако: обратите внимание, что final int ten = 10; final int three = 3; short thirty = ten * three;компилируется нормально.
Marco13
7
If short is automatically promoted to int in arithmetic operations- это не актуально. Ни , 10ни 3не являются шорты и они не способствовали, они литералы.
Мэтью Рид
@MatthewRead: но даже как литералы, они должны оцениваться как определенный тип данных, верно? Так это правда, что 10и 3оцениваются intкомпилятором как s?
LarsH

Ответы:

139

Потому что компилятор заменяет 10*330 во время самой компиляции . Итак, эффективно: 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

TheLostMind
источник
17
понравилось Try changing ten and three to final shortупражнение :)
Сергей Паук
1
@SergeyPauk - Это действительно важно для понимания констант времени компиляции .. применимо ко всем примитивам (в том числе и к
строкам
1
@TheLostMind Я бы предложил лучшую формулировку, you will see that there's no difference (between those two lines in the decompiled code)потому что разве это не ваша точка зрения?
Сергей Паук
4
Забавно, но это также означает, что case 10*3:и подобное разрешено в конструкции переключателя.
Ceiling Gecko
5
То же самое и в конструкциях enum. Фактически, использование таких вещей, как 1 << 5 для констант перечисления битовых полей, идиоматично.
Вирсавия
18

Да, с буквальным регистром происходит что-то особенное: 10 * 3будет оцениваться во время компиляции . Таким образом, вам не нужно явное (short)преобразование для умноженных литералов.

ten * three не оценивается во время компиляции, поэтому требует явного преобразования.

Другое дело, если бы tenи threeбыли отмечены final.

Вирсавия
источник
1

В следующем ответе добавлен раздел JLS и некоторые подробности об этом поведении.

Согласно JLS §15.2 - Формы выражений

Некоторые выражения имеют значение, которое можно определить во время компиляции. Это постоянные выражения (§15.28).

Николя Хено
источник