2013-07-28 11 views
25

Se converto un carattere in byte e poi di nuovo in char, quel personaggio scompare misteriosamente e diventa qualcos'altro. Com'è possibile?Conversione byte e caratteri in Java

Questo è il codice:

char a = 'È';  // line 1  
byte b = (byte)a; // line 2  
char c = (char)b; // line 3 
System.out.println((char)c + " " + (int)c); 

Fino linea 2 è tutto a posto:

  • In linea 1 ho potuto stampare "a" nella console e sarebbe mostrare "E".

  • Nella riga 2 potrei stampare "b" nella console e mostrerebbe -56, ovvero 200 perché il byte è firmato. E 200 è "È". Quindi va ancora bene.

Ma cosa c'è che non va nella riga 3? "c" diventa qualcos'altro e il programma stampa ? 65480. È qualcosa di completamente diverso.

Cosa dovrei scrivere nella riga 3 per ottenere il risultato corretto?

+4

Un 'byte' è' 8 bit'.'char' è' 16 bit'. Hai l'idea? –

+0

char occupa 2 byte. – Ankit

+0

@RohitJain E un carattere, con cui intendo un punto di codice Unicode, può assumere due caratteri o quattro byte. Inoltre, chi sa in quale forma di normalizzazione si trovano le cose? La stringa '" È "' può comprendere a sua volta uno o due punti di codice a seconda che sia in Normalization Form C o D rispettivamente. – tchrist

risposta

44

Un carattere in Java è un'unità di codice Unicode che viene considerata come un numero senza segno. Quindi, se si esegue c = (char)b il valore che si ottiene è 2^16 - 56 o 65536 - 56.

O, più precisamente, il byte è prima convertito in un intero con segno con il valore 0xFFFFFFC8 utilizzando segno estensione in una conversione di ampliamento . Questo a sua volta viene quindi ridotto a 0xFFC8 quando si esegue il casting su un char, che si traduce nel numero positivo 65480.

Dalla descrizione lingua:

5.1.4. Widening and Narrowing Primitive Conversion

Innanzitutto, il byte viene convertito in un int tramite allargamento conversione primitiva (§5.1.2), e quindi l'int risultante viene convertito in un char riducendo la conversione primitiva (§5.1.3).


Per ottenere l'uso punto giusto char c = (char) (b & 0xFF) che converte il valore di byte di b al numero intero positivo 200 utilizzando una maschera, azzerando i primi 24 bit dopo la conversione: 0xFFFFFFC8 diventa 0x000000C8 o il numero positivo 200 in decimali.


supera una spiegazione diretta di ciò che accade durante la conversione tra i byte, int e char tipi primitivi.

Se si vuole codificare i caratteri/decodifica di byte, utilizzare Charset, CharsetEncoder, CharsetDecoder o uno dei metodi di convenienza, come new String(byte[] bytes, Charset charset) o String#toBytes(Charset charset). È possibile ottenere il set di caratteri (come UTF-8 o Windows-1252) da StandardCharsets.

+3

In realtà, un 'char' Java non è un codice Unicode * ** punto ***. È un codice UTF-16 * ** unità ***. Per rappresentare effettivamente un "carattere" Unicode arbitrario (con cui intendo un vero punto di codice), un 'char' di Java non è abbastanza buono: devi usare un' int' (che ti dà effettivamente UTF-32), che può occupare a due caratteri nella notazione UTF-16 legacy. Ecco perché tutto ha un'API 'codePointAt', non solo la cattiva vecchia legacy' charAt' API. – tchrist

+1

@tchrist sì, questo è cambiato un po 'quando Unicode ha superato il bordo di 64Ki. –

+0

Perché il 'char c = (char) (b & 0xFF)' usa solo un singolo byte, quando i caratteri Java devono essere due byte? – statueofmike