Чому "короткий тридцять = 3 * 10" є юридичним завданням?


102

Якщо в арифметичних операціях 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).
Томас

Компілятор обчислює 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


17
сподобалася Try changing ten and three to final shortвправа :)
Сергій Паук

1
@SergeyPauk - Це дійсно важливо для розуміння констант часу компіляції .. стосується всіх примітивів (а також рядків ..) :)
TheLostMind

1
@TheLostMind Я б запропонував краще формулювати you will see that there's no difference (between those two lines in the decompiled code)причину, чи не це ваша суть?
Сергій Паук

4
Забавно, це також означає, що case 10*3:подібне є законним у конструкції комутатора.
Стеля Гекко

5
І аналогічно в конструкціях enum. Насправді, використання таких елементів, як 1 << 5 для констант бітфілмуму, є ідіоматичним.
Вірсавія

18

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

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

Було б інше питання, якби tenі threeбули позначені final.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.