2009-12-20 14 views
9

Estoy a punto de empezar a trabajar en algo que requiere la lectura de bytes y la creación de cadenas. Los bytes que se leen representan cadenas UTF-16. Entonces, para probar cosas, quería convertir una matriz de bytes simple en codificación UTF-16 en una cadena. Los primeros 2 bytes en la matriz deben representar la endianidad, por lo que deben ser 0xff 0xfe o 0xfe 0xff. Así que he intentado crear mi matriz de bytes de la siguiente manera:Conversión implícita de Java de int a byte

byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00}; 

Pero tengo un error porque 0xFF y 0xFE son demasiado grandes para caber en un byte (porque bytes se firman en Java). Más precisamente, el error fue que el int no se pudo convertir en un byte. Sé que podría convertir explícitamente de int a byte con un elenco y lograr el resultado deseado, pero de eso no se trata mi pregunta.

Para probar algo, creé un String y llamé getBytes ("UTF-16") y luego imprimí cada uno de los bytes del conjunto. La salida fue un poco confusa porque los primeros dos bytes fueron 0xFFFFFFFE 0xFFFFFFFF, seguidos por 0x00 0x52 0x00 0x6F. (Obviamente, la endianidad aquí es diferente de lo que intentaba crear arriba, pero eso no es importante).

Utilizando esta salida decidí probar y crear mi matriz de bytes de la misma manera:

byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00}; 

Y curiosamente funcionó bien. Entonces mi pregunta es, ¿por qué Java permite que un valor entero de 0xFFFFFF80 o superior se convierta automáticamente a un byte sin un molde explícito, pero cualquier valor igual o mayor a 0x80 requiere un lanzamiento explícito?

Respuesta

10

La clave a recordar aquí es que int en Java es un valor con signo. Cuando asigna 0xffffffff (que es 2^32 -1), esto se traduce en un int firmado de valor -1 - un int no puede representar algo tan grande como 0xffffffff como un número positivo.

Por lo tanto, para valores menores que 0x80 y mayores que 0xFFFFFF80, el valor int resultante está entre -128 y 127, que puede ser inequívocamente representado como byte. Cualquier cosa fuera de ese rango no puede ser, y necesita forzar con un lanzamiento explícito, perdiendo datos en el proceso.

+0

Gracias, eso lo hace mucho más claro. – DaveJohnston

2

Si utiliza un número sin una pista (por ejemplo, 1234L durante un tiempo), el compilador supone un número entero. El valor 0xffffffff es un número entero con el valor -1 que se puede convertir a byte sin previo aviso.

+1

... porque Java usa notación complementaria de dos para valores negativos. – Ash

0

Porque 0xffffffff es el número -1 y -1 se puede interpretar como un byte.

0

0xff es lo mismo que escribir 0x000000ff, no 0xffffffff. Entonces ese es tu problema; el número entero es un número positivo (255), pero el byte (si se convierte bit a bit) sería un número negativo (-1). Pero 0xffffffff es -1 como int y como byte.

0

Porque int está firmado y 0xffffffff representa -1, y 0xff representa un número entero de 255, que no se encuentra en -128 (0x80) +127 (0x7f) rango de un byte.