web-dev-qa-db-fra.com

Pourquoi "short trente = 3 * 10" est une mission légale?

Si short est automatiquement promu en int dans les opérations arithmétiques, alors pourquoi:

short thirty = 10 * 3;

Une affectation légale à la variable shortthirty?

À 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 se compile pas car l'attribution d'une valeur int à un short n'est pas autorisée sans transtypage comme prévu.

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

100
Ceiling Gecko

Parce que le compilateur remplace 10*3 avec 30 à temps de compilation lui-même. Donc, effectivement: short thirty = 10 * 3 est calculé au moment de la compilation.

Essayez de remplacer ten et three par final short (en leur faisant compiler des constantes de temps) et voir ce qui se passe: P

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

Ok, alors, 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;
}

Code octet:

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, 10 et 3 sont extraits des variables locales s1 et s2

137
TheLostMind

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

ten * three n'est pas évaluable au moment de la compilation et a donc besoin d'une conversion explicite.

Ce serait différent si ten et three étaient marqués final.

18
Bathsheba

Ce qui suit réponse ajoute la section JLS et quelques détails sur ce comportement.

Selon JLS §15.2 - Formes d'expressions

Certaines expressions ont une valeur qui peut être déterminée au moment de la compilation. Ce sont des expressions constantes (§15.28).

0
Nicolas Henneaux