Perché "trenta brevi = 3 * 10" è un incarico legale?


102

Se shortviene promosso automaticamente a intnelle operazioni aritmetiche, perché è:

short thirty = 10 * 3;

Un'assegnazione legale alla shortvariabile thirty?

A sua volta, questo:

short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

oltre a questo:

int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

non si compila perché l'assegnazione di un intvalore a a shortnon è consentita senza eseguire il cast come previsto.

C'è qualcosa di speciale sui letterali numerici?


23
short thirty = 10 * 3;molto probabilmente è sostituito dal short thirty = 30;compilatore che è un'istruzione valida allora. (Dovrei cercare la sezione JLS pertinente però).
— Thomas,

Il compilatore calcola 10 * 3e inizializza la variabile con il risultato. Nel tuo esempio non funzionante il calcolo avviene in fase di runtime in cui JVM lancia lo short.
— Felix

Penso che questo sia un duplicato, di stackoverflow.com/questions/30346587/java-char-to-byte-casting o stackoverflow.com/questions/9379983/… . Tuttavia: nota che si final int ten = 10; final int three = 3; short thirty = ten * three;compila bene.
— Marco13

7
If short is automatically promoted to int in arithmetic operations- non è rilevante. Né 10, né 3sono pantaloncini né sono promossi, sono letterali.
— Matthew Read

@ MatthewRead: ma anche come letterali, devono essere valutati come un particolare tipo di dati, giusto? Quindi è vero che 10e 3vengono valutati come ints dal compilatore?
— LarsH

Risposte:


139

Perché il compilatore sostituisce 10*3con 30 al momento della compilazione stessa. Quindi, effettivamente: short thirty = 10 * 3viene calcolato in fase di compilazione.

Prova a cambiare tene threea final short(facendo in modo che compilino le costanti di tempo) e guarda cosa succede: P

Esaminare il byte-code utilizzando javap -v per entrambe le versioni ( 10*3e final short). Potrai vedere che c'è poca differenza.

Ok, quindi, ecco la differenza del codice byte per casi diversi.

Caso 1 :

Codice Java: main () {short s = 10 * 3; }

Codice byte:

stack=1, locals=2, args_size=1
         0: bipush        30  // directly push 30 into "s"
         2: istore_1      
         3: return   

Caso -2:

public static void main(String arf[])  {
   final short s1= 10;
   final short s2 = 3;
   short s = s1*s2;
}

Codice byte:

  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   

Caso -3:

public static void main(String arf[]) throws Exception {
     short s1= 10;
     short s2 = 3;
     int s = s1*s2;
}

Codice byte:

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 

Nel caso precedente, 10e 3sono presi dalle variabili locali s1es2


17
mi è piaciuto l' Try changing ten and three to final shortesercizio :)
— Sergey Pauk

1
@SergeyPauk - Questo è molto importante per comprendere le costanti del tempo di compilazione .. si applica a tutte le primitive (anche le stringhe ..) :)
— TheLostMind

1
@TheLostMind Suggerirei una migliore formulazione you will see that there's no difference (between those two lines in the decompiled code)perché non è questo il punto?
— Sergey Pauk

4
In modo divertente, questo significa anche che case 10*3:e simili sono legali in un costrutto switch.
— Soffitto Gecko

5
E allo stesso modo nei costrutti enum. In effetti, usare cose come 1 << 5 per le costanti enum bitfield è idiomatico.
— Bathsheba

18

Sì, c'è qualcosa di speciale in corso con il caso letterale: 10 * 3verrà valutato in fase di compilazione . Quindi non hai bisogno di un esplicito(short) conversione per i letterali moltiplicati.

ten * three non è valutabile in fase di compilazione, quindi necessita di una conversione esplicita.

Diverso sarebbe se tene threefossero contrassegnati final.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.