Por que "int i = 2147483647 + 1;" OK, mas "byte b = 127 + 1;" não é compilável?


126

Por que está int i = 2147483647 + 1;OK, mas byte b = 127 + 1;não é compilável?


16
Também tenho uma dúvida genuína: por que o bytetipo de dados é tão doloroso ?!
BoltClock

9
é definitivamente um erro de design byteassinado em vez de não assinado.
irreputável

4
@BoltClock É apenas uma dor quando você não sabe como usá-lo corretamente. stackoverflow.com/questions/397867/…
starblue

2
@ starblue, existe algum exemplo da vida real em que o tipo de byte Java é aplicável?
Thorbjørn Ravn Andersen

Se houver dados especificados como um byte, use um Java bytepara maior clareza, por exemplo, nos parâmetros. Nesse caso, o fato de você não poder atribuir intvalores poderá até pegar alguns bugs. Ou use bytepara economizar espaço em matrizes. Eu não usaria bytepor um único valor que só se encaixa em um byte.
starblue

Respostas:


172

As constantes são avaliadas como ints, portanto, 2147483647 + 1estouram e fornecem um novo int, que é atribuível a int, enquanto 127 + 1também é avaliado como intigual a 128, e não é atribuído a byte.


10
Na verdade, hoje eu li alguns dos puzzlers Java , incluindo um quebra-cabeça apenas sobre isso ... Veja aqui: javapuzzlers.com/java-puzzlers-sampler.pdf - enigma 3
MByD

3
O problema é do tipo intdevido à promoção numérica binária, o valor 127é um arenque vermelho.
31711 starblue

Eu preferiria que constantes fossem avaliadas com precisão infinita e também fornecessem um erro em int i = 2147483647 + 1;
Eduardo

@MByD: Como você disse " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", isso significa que 50 + 1 será avaliado como bytee, portanto, é atribuível a byte?
Bhushan

1
@ 10101010 - não exatamente. será atribuível ao byte, mas primeiro (de acordo com o padrão) será avaliado como int.
MByD 27/10/11

35

O literal 127 denota um valor do tipo int. O mesmo acontece com o literal 1. A soma desses dois é o número inteiro 128. O problema, no segundo caso, é que você está atribuindo isso a uma variável do tipo byte. Não tem nada a ver com o valor real das expressões. Tem a ver com Java que não suporta coerções (*). Você precisa adicionar um typecast

byte b = (byte)(127 + 1);

e depois compila.

(*) pelo menos não do tipo String-to-integer, float-to-Time, ... Java suporta coerções se elas são, de certo modo, sem perda (Java chama isso de "ampliação").

E não, a palavra "coerção" não precisava ser corrigida. Foi escolhido de maneira muito deliberada e correta. Da fonte mais próxima em mão (Wikipedia): "Na maioria dos idiomas, a palavra coerção é usada para denotar uma conversão implícita , durante a compilação ou durante o tempo de execução". e "Na ciência da computação, conversão de tipos, conversão de tipos e coerção são formas diferentes de, implícita ou explicitamente, alterar uma entidade de um tipo de dados para outro".


Seu exemplo de código provavelmente deve ser byte b = (byte) 127 + 1; que é 'Adicionar 1 a um valor máximo de bytes', seu exemplo apenas transforma o valor int de 128 em um valor de byte.
NKCSS

6
@NKCSS - Eu não acho que você esteja certo - converta (byte)(127 + 1)128 (número inteiro) em um byte, enquanto isso (byte)127 + 1converte 127 em um byte, mas novamente em um int, já que é adicionado a 1 (int) e você obtenha 128 (int) e o erro permanece.
MByD 31/07

6

Como evidência para @MByD:

O seguinte código compila:

byte c = (byte)(127 + 1);

Porque, embora a expressão (127 + 1)seja int e esteja fora do escopo, byteo resultado é convertido byte. Essa expressão produz -128.


3

Conversão de atribuição JLS3 # 5.2

(variável = expressão)

Além disso, se a expressão for uma expressão constante (§15.28) do tipo byte, short, char ou int:

Uma conversão primitiva de restrição pode ser usada se o tipo da variável for byte, short ou char, e o valor da expressão constante for representável no tipo da variável.


Sem essa cláusula, não poderíamos escrever

byte x = 0;
char c = 0;

Mas devemos ser capazes de fazer isso? Acho que não. Há muita mágica acontecendo na conversão entre os primitivos, é preciso ter muito cuidado. Eu me esforçava para escrever

byte x = (byte)0;

quanto à pergunta que deveríamos ser capazes de ... eu não vejo realmente nada de errado com isso, byte x = 0mas, novamente, eu sou um programador em C.
Grady Player

Talvez eu pudesse ver um argumento contra char c = 0, mas por que o byte x = 0 está errado?
Michael Burge

É enganoso para olhos não treinados, pensando que eles estão atribuindo um byte 0 a uma variável de byte. Não há muitos danos neste exemplo, mas, em geral, operar em byte / short / char pode ficar muito confuso devido a conversões implícitas. Eles são muito mais complicados do que as pessoas pensariam. Quero o máximo de clareza possível no meu código, não introduza nenhuma incerteza com o objetivo de salvar alguns pressionamentos de tecla.
#

Uma regra semelhante se aplica quando a conversão primitiva de restrição é longa para int, por exemplo, int i = 1 + 0L? Basta perguntar, porque o texto citado explicitamente deixa esse caso de fora.
Erwin Smout

@ Erwin não, int i=0Lé ilegal.
irreputável
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.