it-swarm.com.de

Char in Byte? (Java)

Wie kommt das?

char a = '\uffff'; //Highest value that char can take - 65535
byte b = (byte)a; //Casting a 16-bit value into 8-bit data type...! Isn't data lost here?
char c = (char)b; //Let's get the value back
int d = (int)c;
System.out.println(d); //65535... how?

Im Grunde habe ich gesehen, dass ein char 16-Bit ist. Wenn Sie es in ein byte umwandeln, warum gehen dann keine Daten verloren? (Wert ist derselbe nach dem Abgießen in ein int)

Vielen Dank im Voraus für die Beantwortung dieser kleinen ignoranten Frage von mir. : P

EDIT: Woah, habe herausgefunden, dass meine ursprüngliche Ausgabe tatsächlich wie erwartet funktioniert hat, aber ich habe gerade den obigen Code aktualisiert. Grundsätzlich wird ein Charakter in ein Byte gegossen und dann wieder in ein Zeichen umgewandelt, und der ursprüngliche 2-Byte-Wert bleibt erhalten. Wie kommt es dazu?

15
wakachamo

Wie trojanfoe feststellt, ist Ihre Verwirrung bezüglich der Ergebnisse Ihres Codes zum Teil auf die Erweiterung des Zeichens zurückzuführen. Ich werde versuchen, eine ausführlichere Erklärung hinzuzufügen, die bei Ihrer Verwirrung helfen kann.

char a = '\uffff';
byte b = (byte)a;  // b = 0xFF

Wie Sie bemerkt haben, führt dies zu Informationsverlust. Dies wird als Verengungskonvertierung betrachtet. Beim Konvertieren eines Zeichens in ein Byte werden einfach alle Bits außer den n niedrigstwertigen Bits verworfen.
.__ Das Ergebnis ist: 0xFFFF -> 0xFF

char c = (char)b;  // c = 0xFFFF

Die Umwandlung eines Bytes in ein Zeichen gilt als spezielle Umwandlung . Es führt tatsächlich ZWEI Konvertierungen durch. Zunächst wird das Byte SIGN-erweitert (die neuen höherwertigen Bits werden vom alten Vorzeichenbit kopiert) in ein int (eine normale Konvertierungserweiterung). Zweitens wird das int in ein Zeichen mit einer einschränkenden Umwandlung konvertiert.
.__ Das Ergebnis ist: 0xFF -> 0xFFFFFFFF -> 0xFFFF

int d = (int)c;  // d = 0x0000FFFF

Das Konvertieren eines Zeichens in ein int wird als erweiternde Konvertierung betrachtet. Wenn ein Zeichentyp auf einen ganzzahligen Typ erweitert wird, wird er NULL-erweitert (die neuen höherwertigen Bits werden auf 0 gesetzt).
.__ Das Ergebnis ist: 0xFFFF -> 0x0000FFFF. Wenn Sie gedruckt werden, erhalten Sie 65535.

Bei den drei Links, die ich zur Verfügung gestellt habe, handelt es sich um die offiziellen Java-Sprachspezifikationsdetails für primitive Typkonvertierungen. Ich empfehle Ihnen dringend, einen Blick darauf zu werfen. Sie sind nicht furchtbar wortreich (und in diesem Fall relativ einfach). Es beschreibt genau, was Java hinter den Kulissen mit Typumwandlungen macht. Dies ist ein üblicher Missverständnisbereich für viele Entwickler. Schreiben Sie einen Kommentar, wenn Sie noch mit einem Schritt verwechselt werden.

23
robert_x44

Es ist Vorzeichenerweiterung . Versuchen Sie \u1234 anstelle von \uffff und sehen Sie, was passiert.

8
trojanfoe

Java byte ist signiert. es ist gegen intuitiv. In fast allen Situationen, in denen ein Byte verwendet wird, möchten Programmierer stattdessen ein Byte ohne Vorzeichen. Es ist sehr wahrscheinlich ein Fehler, wenn ein Byte direkt in int umgewandelt wird. 

Dadurch wird die beabsichtigte Konvertierung in fast allen Programmen korrekt durchgeführt:

int c = 0xff & b ;

Empirisch ist die Wahl des signierten Bytes ein Fehler.

5
irreputable

Etwas seltsames Zeug auf deiner Maschine. Schauen Sie sich die Java-Sprachspezifikation an, Kapitel 4.2.1 :

Die Werte der Integraltypen sind ganze Zahlen in den folgenden Bereichen:

Für Byte von -128 bis einschließlich 127

... schnipp andere ...

Wenn Ihre JVM standardkonform ist, sollte Ihre Ausgabe -1 sein. 

0
darioo