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.