¿Por qué "treinta cortos = 3 * 10" es una asignación legal?

102

Si shortse promueve automáticamente a inten operaciones aritméticas, entonces por qué es:

short thirty = 10 * 3;

¿Una cesión legal a la shortvariable 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 intvalor a a shortsin convertir como se esperaba.

¿Está sucediendo algo especial con los literales numéricos?

Gecko de techo
fuente
23
short thirty = 10 * 3;Lo más probable es que sea reemplazado por short thirty = 30;el compilador, que es una declaración válida. (Sin embargo, tendría que buscar la sección JLS relevante).
Thomas
El compilador calcula 10 * 3e inicializa la variable con el resultado. En su ejemplo no funcional, el cálculo ocurre en tiempo de ejecución donde la JVM lanza el corto.
Felix
Creo que esto es un duplicado de stackoverflow.com/questions/30346587/java-char-to-byte-casting o stackoverflow.com/questions/9379983/… . Sin embargo: tenga en cuenta que se final int ten = 10; final int three = 3; short thirty = ten * three;compila bien.
Marco13
7
If short is automatically promoted to int in arithmetic operations- eso no es relevante. Ni 10tampoco 3son cortos ni son promovidos, son literales.
Matthew Read
@MatthewRead: pero incluso como literales, tienen que ser evaluados como un tipo de datos en particular, ¿verdad? Entonces, ¿es cierto que 10y el compilador los 3evalúa como ints?
LarsH

Respuestas:

139

Porque el compilador reemplaza 10*3con 30 en el tiempo de compilación . Entonces, efectivamente: short thirty = 10 * 3se calcula en tiempo de compilación.

Prueba a cambiar teny threeque final short(por lo que las constantes de tiempo de compilación) y ver lo que sucede: P

Examine el uso de código de bytes javap -v para ambas versiones ( 10*3y final short). Podrás ver que hay poca diferencia.

Bien, aquí está la diferencia de código de bytes para diferentes casos.

Caso 1 :

Código Java: main () {short s = 10 * 3; }

Código de 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;
}

Código de 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;
}

Código de 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 

En el caso anterior, 10y 3se toman de las variables locales s1ys2

TheLostMind
fuente
17
gustó el Try changing ten and three to final shortejercicio :)
Sergey Pauk
1
@SergeyPauk: eso es realmente importante para comprender las constantes de tiempo de compilación ... se aplica a todas las primitivas (cadenas también ...) :)
TheLostMind
1
@TheLostMind Sugeriría una mejor redacción you will see that there's no difference (between those two lines in the decompiled code)porque ¿no es este tu punto?
Sergey Pauk
4
Curiosamente, esto también significa que case 10*3:y similar es legal en una construcción de interruptor.
Ceiling Gecko
5
Y de manera similar en las construcciones enum. De hecho, usar cosas como 1 << 5 para constantes de enumeración de campo de bits es idiomático.
Betsabé
18

Sí, hay algo especial en el caso literal: 10 * 3se evaluará en el momento de la compilación . Por lo tanto, no necesita una (short)conversión explícita para literales multiplicados.

ten * three no es evaluable en tiempo de compilación, por lo que necesita una conversión explícita.

Sería diferente si teny threeestuvieran marcados final.

Betsabé
fuente
1

La siguiente respuesta 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).

Nicolás Henneaux
fuente