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 short
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 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?
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
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
.
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).