Java:por que recebo a mensagem de erro “Tipo incompatível:não é possível converter int em byte”
-
09-06-2019 - |
Pergunta
Se você declarar variáveis do tipo byte ou short e tentar realizar operações aritméticas sobre elas, receberá o erro "Tipo incompatível:não é possível converter int em short" (ou correspondentemente "Incompatibilidade de tipo:não é possível converter int em byte").
byte a = 23;
byte b = 34;
byte c = a + b;
Neste exemplo, o erro de compilação está na terceira linha.
Solução
Embora os operadores aritméticos são definidos para operar em qualquer tipo numérico, de acordo com a especificação da linguagem Java (5.6.2 Binário Promoção Numérico), operandos do tipo byte e curtas são automaticamente promovidos para int antes de ser entregue aos operadores.
Para executar operações aritméticas em variáveis ??do tipo byte ou curto, você deve colocar a expressão entre parênteses (dentro dos quais as operações serão realizadas como tipo int), e depois expressos nas costas resultado para o tipo desejado.
byte a = 23; byte b = 34; byte c = (byte) (a + b);
Aqui está um follow-on pergunta aos gurus Java reais: por quê? O byte tipos e curta são perfeitamente bem tipos numéricos. Por que Java não permite operações aritméticas diretos sobre esses tipos? (A resposta não é "perda de precisão", como não há nenhuma razão aparente para converter para int em primeiro lugar.)
Update: jrudolph sugere que este comportamento é baseado nas operações disponíveis na JVM, especificamente, que apenas os operadores integral e duas palavras são implementadas. Assim, para operador em bytes e shorts, eles devem ser convertidos para int.
Outras dicas
A resposta à sua pergunta de follow-up é aqui:
operandos do tipo byte e short são automaticamente promovidos para int antes de ser entregue aos operadores
Assim, no seu exemplo, a
e b
são ambos convertidos para um int
antes de ser entregue ao operador +. O resultado da adição de dois int
s juntos é também um int
. Tentando, em seguida, atribuir esse int
para um valor byte
causa o erro porque há uma perda potencial de precisão. Ao lançar explicitamente o resultado que você está dizendo o compilador "Eu sei o que estou fazendo".
Eu acho que, a questão é, que os suportes JVM apenas dois tipos de valores da pilha: palavra size e palavra dupla de tamanho.
Em seguida, eles provavelmente decidiram que seria necessário apenas uma operação que funciona em palavra dimensionado inteiros na pilha. Então só há iadd, IMUL e assim por diante a nível bytecode (e há operadores para bytes e shorts).
Para que você obtenha um valor de int como resultado dessas operações que Java não pode converter com segurança de volta para o byte menor e tipos de dados curtos. Então eles forçá-lo a elenco para reduzir o valor de volta para byte / short.
Mas no final você está certo: Este comportamento não é consistente com o comportamento de inteiros, por exemplo. Você pode sem problema adicionar dois inteiros e obter nenhum erro se o resultado transborda.
A linguagem Java sempre promove argumentos dos operadores aritméticos para int, long, float ou double. Portanto, tome a expressão:
a + b
em que a e b são de tipo byte. Este é um atalho para:
(int)a + (int)b
Esta expressão é do tipo int. É claramente faz sentido dar um erro ao atribuir um valor int para uma variável byte.
Por que a língua ser definida desta forma? Suponhamos que uma era de 60 e de b foi de 70, então a + b é -126 - número inteiro de transbordamento. Como parte de uma expressão mais complicada que era esperado para resultar em um int, isso pode se tornar um problema difícil. Restringir o uso de byte e curta a matriz de armazenamento, constantes para formatos de arquivo / protocolos de rede e puzzlers.
Há uma gravação interessante do JavaPolis 2007. James Gosling está dando um exemplo sobre como complicado aritmética sem sinal é (e por que não é em Java). Josh Bloch assinala que o seu exemplo dá o exemplo errado sob aritmética assinado normal também. Para aritmética compreensível, precisamos de precisão arbitrária.