Pourquoi «court trente = 3 * 10» est une cession légale?


103

Si shortest automatiquement promu intdans les opérations arithmétiques, alors pourquoi:

short thirty = 10 * 3;

Une affectation légale à la shortvariable thirty?

À son tour, ceci:

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

ainsi que cette:

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

ne compile pas car l'attribution d'une intvaleur à a shortn'est pas autorisée sans la conversion comme prévu.

Y a-t-il quelque chose de spécial à propos des littéraux numériques?


23
short thirty = 10 * 3;est très probablement remplacé par short thirty = 30;le compilateur qui est alors une instruction valide. (Je devrais cependant rechercher la section JLS pertinente).
Thomas

Le compilateur calcule 10 * 3et initialise la variable avec le résultat. Dans votre exemple non fonctionnel, le calcul se produit au moment de l'exécution, où la JVM lance le court-circuit.
Felix

Je pense que c'est un doublon, de stackoverflow.com/questions/30346587/java-char-to-byte-casting ou stackoverflow.com/questions/9379983/… . Cependant: notez que final int ten = 10; final int three = 3; short thirty = ten * three;compile bien.
Marco13

7
If short is automatically promoted to int in arithmetic operations- ce n'est pas pertinent. Ni 10ne 3sont courts et ne sont pas promus, ils sont littérales.
Matthew Lire

@MatthewRead: mais même en tant que littéraux, ils doivent être évalués comme un type de données particulier, non? Alors est-il vrai que 10et 3sont évalués comme ints par le compilateur?
LarsH

Réponses:


139

Parce que le compilateur remplace 10*3par 30 au moment de la compilation . Donc, effectivement: short thirty = 10 * 3est calculé au moment de la compilation.

Essayez de changer tenet threede final short(en leur faisant compiler des constantes de temps) et voyez ce qui se passe: P

Examinez le code d'octet en utilisant javap -v pour les deux versions ( 10*3et final short). Vous pourrez voir qu'il y a peu de différence.

Ok, donc, voici la différence de code d'octet pour différents cas.

Cas 1 :

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

Code d'octet:

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

Cas -2:

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

Code d'octet:

  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   

Cas -3:

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

Byte-code:

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 

Dans le cas ci-dessus, 10et 3sont tirés des variables locales s1ets2


17
aimé l' Try changing ten and three to final shortexercice :)
Sergey Pauk

1
@SergeyPauk - C'est vraiment important pour comprendre les constantes de temps de compilation .. s'applique à toutes les primitives (Strings aussi ..) :)
TheLostMind

1
@TheLostMind Je suggérerais une meilleure formulation you will see that there's no difference (between those two lines in the decompiled code)car n'est-ce pas votre propos?
Sergey Pauk

4
De manière amusante, cela signifie également que case 10*3:et similaire est légal dans une construction de commutateur.
Ceiling Gecko

5
Et de même dans les constructions enum. En fait, utiliser des trucs comme 1 << 5 pour les constantes d'énumération de champ de bits est idiomatique.
Bathsheba

18

Oui, il se passe quelque chose de spécial avec le cas littéral: 10 * 3sera évalué au moment de la compilation . Vous n'avez donc pas besoin d'une (short)conversion explicite pour les littéraux multipliés.

ten * three n'est pas évaluable à la compilation et nécessite donc une conversion explicite.

Ce serait une autre question si tenet threeétaient marqués final.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.