java - ¿Por qué "short treinta=3*10" es una asignación legal?
type-promotion (3)
Si
short
se promociona automáticamente a
int
en operaciones aritméticas, entonces por qué es:
short thirty = 10 * 3;
¿Una asignación legal a la variable
short
thirty
?
A su vez, esto:
short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
tan bien como esto:
int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
no se compila porque no se permite asignar un valor
int
a un
short
sin convertir como se esperaba.
¿Hay algo especial en los literales numéricos?
La siguiente answer agrega la sección JLS y algunos detalles sobre este comportamiento.
Según JLS §15.2 - Formas de expresiones
Algunas expresiones tienen un valor que se puede determinar en tiempo de compilación. Estas son expresiones constantes (§15.28).
Porque el compilador reemplaza
10*3
con 30 en
tiempo de compilación
.
Entonces, efectivamente:
short thirty = 10 * 3
se calcula en tiempo de compilación.
Intente cambiar
ten
y
three
a
final short
(haciendo que compilen constantes de tiempo) y vea qué sucede: P
Examine el código de bytes usando
javap -v
para ambas versiones (
10*3
y
final short
).
Podrá ver que hay poca diferencia.
Ok, entonces, aquí está la diferencia de código de byte para diferentes casos.
Caso 1 :
Código Java: main () {short s = 10 * 3; }
Código de bytes:
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;
}
Código de bytes:
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;
}
Código de bytes:
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
En el caso anterior,
10
y
3
se toman de las variables locales
s1
y
s2
Sí, hay algo especial en el caso literal:
10 * 3
se evaluará en tiempo de
compilación
.
Por lo tanto, no necesita una conversión explícita
(short)
para literales multiplicados.
ten * three
no es evaluable en tiempo de compilación, por lo tanto, necesita una conversión explícita.
Sería diferente si
ten
y
three
fueran marcados como
final
.