¿Por qué es "int i = 2147483647 + 1;" OK, pero "byte b = 127 + 1;" no es compilable?

126

¿Por qué está int i = 2147483647 + 1;bien, pero byte b = 127 + 1;no es compilable?

goku
fuente
16
También tengo una duda genuina: ¿por qué es tan bytedifícil el tipo de datos?
BoltClock
9
Definitivamente es un error de diseño bytefirmado en lugar de no firmado.
irreputable el
44
@BoltClock Es solo un dolor cuando no sabes cómo usarlo correctamente. stackoverflow.com/questions/397867/…
starblue
2
@starblue, ¿hay algún ejemplo de la vida real en el que sea aplicable el tipo de byte Java?
Thorbjørn Ravn Andersen
Si hay datos que se especifican como un byte, utilice Java bytepara mayor claridad, por ejemplo, en los parámetros. En ese caso, el hecho de que no pueda asignar intvalores incluso detectará algunos errores. O use bytepara ahorrar espacio en matrices. No lo usaría bytepara un solo valor que solo cabe en un byte.
Starblue

Respuestas:

172

Las constantes se evalúan como ints, por lo que se 2147483647 + 1desborda y le da un nuevo int, que se puede asignar a int, mientras que 127 + 1también se evalúa como intigual a 128, y no se puede asignar a byte.

MByD
fuente
10
En realidad, hoy leí algunos de los rompecabezas de Java , incluido un rompecabezas sobre eso ... Ver aquí: javapuzzlers.com/java-puzzlers-sampler.pdf - rompecabezas 3
MByD
3
El problema es el tipo intdebido a la promoción numérica binaria, el valor 127es una pista falsa.
starblue
Preferiría que las constantes se evalúen con precisión infinita y que también den un error en int i = 2147483647 + 1;
Eduardo
@MByD: Como dijiste " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", ¿significa esto que 50 + 1 se evaluará como bytey, por lo tanto, se puede asignar byte?
Bhushan
1
@ 10101010: no exactamente. será asignable a byte, pero primero (según el estándar) se evaluará como int.
MByD
35

El literal 127 denota un valor de tipo int. Lo mismo ocurre con el literal 1. La suma de estos dos es el entero 128. El problema, en el segundo caso, es que está asignando esto a una variable de tipo byte. No tiene nada que ver con el valor real de las expresiones. Tiene que ver con Java que no admite coacciones (*). Tienes que agregar un tipo de letra

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

y luego se compila.

(*) al menos no del tipo String-to-integer, float-to-Time, ... Java admite coacciones si, en cierto sentido, son sin pérdida (Java llama a esto "ensanchamiento").

Y no, la palabra "coerción" no necesitaba corrección. Fue elegido de manera muy deliberada y correcta. De la fuente más cercana a la mano (Wikipedia): "En la mayoría de los idiomas, la palabra coerción se usa para denotar una conversión implícita , ya sea durante la compilación o durante el tiempo de ejecución". y "En ciencias de la computación, la conversión de tipos, la conversión de tipos y la coerción son diferentes formas de, implícita o explícitamente, cambiar una entidad de un tipo de datos a otro".

Erwin Smout
fuente
Su ejemplo de código probablemente debería ser el byte b = (byte) 127 + 1; que es 'Agregar 1 a un valor de byte máximo', su ejemplo simplemente convierte el valor int de 128 en un valor de byte.
NKCSS
66
@NKCSS: no creo que tengas razón, esto: (byte)(127 + 1)emite 128 (entero) a un byte, mientras que esto (byte)127 + 1emite el 127 a un byte, pero luego nuevamente a un int, ya que se agrega a 1 (int) y a ti obtiene 128 (int) y el error permanece.
MByD
6

Como evidencia para @MByD:

El siguiente código compila:

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

Porque aunque la expresión (127 + 1)es int y más allá del alcance fuera del bytetipo, el resultado se convierte en byte. Esta expresión produce -128.

AlexR
fuente
3

Conversión de asignación JLS3 # 5.2

(variable = expresión)

Además, si la expresión es una expresión constante (§15.28) de tipo byte, short, char o int:

Se puede usar una conversión primitiva estrecha si el tipo de la variable es byte, short o char, y el valor de la expresión constante es representable en el tipo de la variable.


Sin esta cláusula, no podríamos escribir

byte x = 0;
char c = 0;

¿Pero deberíamos poder hacer esto? No lo creo. Hay bastante magia sucediendo en la conversión entre primitivas, uno debe tener mucho cuidado. Saldría de mi camino para escribir

byte x = (byte)0;
irreputable
fuente
en cuanto a la pregunta si deberíamos poder ... No veo realmente nada malo, byte x = 0pero, de nuevo, soy un programador en C.
Jugador de Grady el
Tal vez podría ver un argumento en contra de char c = 0, pero ¿por qué el byte x = 0 es incorrecto?
Michael Burge
Es engañoso para los ojos no entrenados, pensando que están asignando un byte 0 a una variable de byte. No hay mucho daño en este ejemplo, pero en general, operar en byte / short / char podría ser muy confuso debido a las conversiones implícitas. Son mucho más complicados de lo que la gente pensaría. Quiero tanta claridad como sea posible en mi código, no introduzca ninguna incertidumbre en aras de guardar algunas pulsaciones de teclas.
irreputable el
¿Se aplica una regla similar cuando la conversión primitiva de estrechamiento es de larga a int, por ejemplo, int i = 1 + 0L? Solo pregunto porque el texto citado omite explícitamente ese caso.
Erwin Smout
@Erwin no, int i=0Les ilegal.
irreputable el