¿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?


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


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.


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.