Por que “trinta curtos = 3 * 10” é uma atribuição legal?


102

Se shortfor automaticamente promovido a intem operações aritméticas, então por que:

short thirty = 10 * 3;

Uma atribuição legal para a shortvariável thirty?

Por sua vez, este:

short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

assim como isso:

int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

não compila porque atribuir um intvalor a a shortnão é permitido sem a projeção conforme o esperado.

Há algo especial acontecendo com os literais numéricos?


23
short thirty = 10 * 3;é provavelmente substituído pelo short thirty = 30;compilador, que é uma instrução válida. (Eu teria que procurar a seção JLS relevante).
Thomas

O compilador calcula 10 * 3e inicializa a variável com o resultado. Em seu exemplo não funcional, o cálculo acontece no tempo de execução onde a JVM converte o curto.
Felix

Acho que esta é uma duplicata, de stackoverflow.com/questions/30346587/java-char-to-byte-casting ou stackoverflow.com/questions/9379983/… . No entanto: Observe que final int ten = 10; final int three = 3; short thirty = ten * three;compila bem.
Marco13

7
If short is automatically promoted to int in arithmetic operations- isso não é relevante. Nem 10nem 3são calções nem são promovidos, eles são literais.
Mateus leu

@MatthewRead: mas mesmo como literais, eles precisam ser avaliados como um tipo de dados específico, certo? Portanto, é verdade que 10e 3são avaliados como ints pelo compilador?
LarsH

Respostas:


139

Porque o compilador substitui 10*330 no próprio tempo de compilação . Então, efetivamente: short thirty = 10 * 3é calculado em tempo de compilação.

Tente mudar tene threepara final short(fazendo-os compilar constantes de tempo) e veja o que acontece: P

Examine o código de byte usando javap -v para ambas as versões ( 10*3e final short). Você verá que há pouca diferença.

Ok, então, aqui está a diferença do código de byte 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 

No caso acima, 10e 3são retirados das variáveis ​​locais s1es2


17
gostou do Try changing ten and three to final shortexercício :)
Sergey Pauk

1
@SergeyPauk - Isso é realmente importante para entender as constantes de tempo de compilação .. aplica-se a todos os primitivos (Strings também ..) :)
TheLostMind

1
@TheLostMind Eu sugeriria uma you will see that there's no difference (between those two lines in the decompiled code)causa de formulação melhor, não é esse o seu ponto?
Sergey Pauk

4
Curiosamente, isso também significa que case 10*3:e similar é legal em uma construção de switch.
Ceiling Gecko

5
E da mesma forma em construções enum. Na verdade, usar coisas como 1 << 5 para constantes de enum de campo de bits é idiomático.
Bathsheba

18

Sim, há algo especial acontecendo com o caso literal: 10 * 3será avaliado em tempo de compilação . Portanto, você não precisa de uma (short)conversão explícita para literais multiplicados.

ten * three não é avaliável em tempo de compilação, portanto, precisa de uma conversão explícita.

Seria diferente se tene threefosse marcado final.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.