2009-12-20 21 views
9

Sto per iniziare a lavorare su qualcosa che richiede la lettura di byte e la creazione di stringhe. I byte letti sono le stringhe UTF-16. Quindi, per testare le cose, volevo convertire un semplice array di byte nella codifica UTF-16 in una stringa. I primi 2 byte dell'array devono rappresentare l'endianness e quindi devono essere 0xff 0xfe o 0xfe 0xff. Così ho cercato di creare il mio array di byte come segue:Conversione implicita Java di int a byte

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 poteva essere convertito in un byte. So che potrei semplicemente convertire esplicitamente da int a byte con un cast e ottenere il risultato desiderato, ma non è quello di cui si tratta.

Solo per provare qualcosa ho creato una stringa e chiamato getBytes ("UTF-16"), quindi stampato ciascuno dei byte nella matrice. L'output era leggermente confuso perché i primi due byte erano 0xFFFFFFFE 0xFFFFFFFF, seguito da 0x00 0x52 0x00 0x6F. (Obvisouly il 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 consente a un valore intero di 0xFFFFFF80 o superiore di essere automaticamente convertito in un byte senza un cast esplicito, ma qualcosa di uguale o maggiore di 0x80 richiede un cast esplicito?

risposta

10

La cosa fondamentale da ricordare qui è che int in Java è un valore firmato. Quando si assegna 0xffffffff (che è 2^32 -1), questo viene tradotto in un valore int con segno -1 - un int non può effettivamente rappresentare qualcosa di grande come 0xffffffff come numero positivo.

Quindi per valori inferiori a 0x80 e superiori a 0xFFFFFF80, il valore risultante int è compreso tra -128 e 127, che può essere rappresentato senza ambiguità come byte. Qualsiasi cosa al di fuori di tale intervallo non può essere, e deve forzare con un cast esplicito, perdendo i dati nel processo.

+0

Grazie, questo lo rende molto più chiaro. – DaveJohnston

2

Se si utilizza un numero senza un suggerimento (ad esempio 1234 L per un lungo), il compilatore assume un numero intero. Il valore 0xffffffff è un numero intero con valore -1 che può essere trasmesso a byte senza un avviso.

+1

... perché Java utilizza la notazione a complemento a due per valori negativi. – Ash

0

Poiché 0xffffffff è il numero -1 e -1 può essere interpretato come un byte.

0

0xff è la stessa di scrittura 0x000000ff, non 0xffffffff. Quindi questo è il tuo 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 sia come byte.

0

Poiché int è firmato e 0xffffffff rappresenta -1 e 0xff rappresenta un numero intero di 255, che non giace nell'intervallo -128 (0x80) +127 (0x7f) di un byte.