Java implicita conversione di int a byte
Domanda
che sto per iniziare a lavorare su qualcosa che i byte richiede la lettura e la creazione di stringhe. I byte vengono letti rappresentano UTF-16 stringhe. Quindi, solo per collaudare il tutto ho voluto trasformare un semplice array di byte nella codifica UTF-16 in una stringa. I primi 2 byte nella matrice devono rappresentare l'endianness e quindi devono essere o 0xfe 0xff o 0xfe 0xFF. Così ho cercato di creare il mio array di byte come segue:
byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00};
Ma ho ottenuto un errore perché 0xFF 0xFE e sono troppo grandi per inserirsi in un byte (perché i byte vengono firmati in Java). Più precisamente l'errore era che l'int non può essere convertito in un byte. So che ho potuto solo convertire in modo esplicito da int a byte con un cast e ottenere il risultato desiderato, ma non è quello che la mia domanda è circa.
solo per provare qualcosa che ho creato una stringa e chiamai getBytes ( "UTF-16"), poi stampata ciascuno dei byte nella matrice. L'uscita era leggermente confusa perché i primi due byte sono 0xFFFFFFFE 0xFFFFFFFF, seguita da 0x00 0x52 0x00 0x6F. (Obvisouly l'endianness qui è diverso da quello che stavo cercando di creare sopra, ma che non è importante).
Utilizzando questa uscita ho deciso di provare a creare il mio array di byte allo stesso modo:
byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00};
E stranamente ha funzionato bene. Quindi la mia domanda è, perché Java permette un valore intero di 0xFFFFFF80 o superiore da convertire automaticamente in un byte, senza un cast esplicito, ma nulla di uguale o maggiore di 0x80 richiede un cast esplicito?
Soluzione
La cosa fondamentale da ricordare è che int
in Java è un valore con segno. Quando si assegna 0xffffffff
(che è 2^32 -1
), questo si traduce in un int firmato valore -1
-. Un int
non può di fatto rappresentare qualcosa di grande come 0xffffffff
come un numero positivo
Quindi per valori inferiori a 0x80 e maggiore di 0xFFFFFF80, il valore risultante è int
tra -128 e 127, che può essere univocamente rappresentata come byte
. Tutto ciò al di fuori di tale intervallo non può essere, e ha bisogno di forzare con un cast esplicito, la perdita di dati durante il processo.
Altri suggerimenti
Se si utilizza un numero senza un suggerimento (ad esempio 1234L a lungo) il compilatore assume un numero intero. Il valore 0xffffffff
è un numero intero con valore -1
che può essere fuso ad byte
senza un avviso.
Poiché 0xffffffff è il numero -1 e -1 può essere interpretato come un byte.
0xff
è lo stesso di scrittura 0x000000ff
, non 0xffffffff
. Ecco, questo è il problema; il numero intero è un numero positivo (255), ma il byte (se convertito bit per bit) sarebbe un numero negativo (-1). Ma 0xffffffff
è -1 sia come int
e come byte
.
Poiché int vengono firmati e 0xffffffff rappresentano -1, e 0xFF rappresentano un numero intero di valore 255, che non si trovano in -128 (0x80) +127 (0x7f) della portata di un byte.