Почему "короткий тридцать = 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 не допускается без кастинга, как ожидалось.

Есть ли что-то особенное о числовых литералах?

Ответ 1

Поскольку компилятор заменяет 10*3 на 30 во время компиляции. Таким образом, эффективно: short thirty = 10 * 3 вычисляется во время компиляции.

Попробуйте изменить ten и three на final short (сделав их константами времени компиляции) и посмотрим, что произойдет: P

Изучите байт-код, используя javap -v для обеих версий (10*3 и final short). Вы сможете увидеть, что есть небольшая разница.

Итак, вот разность байтовых кодов для разных случаев.

Случай -1:

Код Java:     главный() {         короткий 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

Ответ 2

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

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

Было бы иначе, если бы были отмечены ten и three final.

Ответ 3

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

По JLS §15.2 - Формы выражений

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