2009-12-20 9 views
9

Ich bin im Begriff, an etwas zu arbeiten, das das Lesen von Bytes und das Erstellen von Strings erfordert. Die gelesenen Bytes repräsentieren UTF-16-Strings. Um die Dinge zu testen, wollte ich ein einfaches Byte-Array in UTF-16-Codierung in eine Zeichenfolge konvertieren. Die ersten 2 Bytes im Array müssen die Endianness darstellen und müssen entweder 0xff 0xfe oder 0xfe 0xff sein. Also habe ich versucht, meine Byte-Array wie folgt zu erstellen:Java implizite Konvertierung von int in Byte

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

Aber ich habe einen Fehler, da 0xFF und 0xFE zu groß sind, in ein Byte zu passen (weil Bytes unterzeichnet werden in Java). Genauer gesagt bestand der Fehler darin, dass der Int nicht in ein Byte konvertiert werden konnte. Ich weiß, dass ich bei einem Cast einfach von int in byte konvertieren und das gewünschte Ergebnis erzielen kann, aber darum geht es bei meiner Frage nicht.

Um etwas auszuprobieren, habe ich einen String erstellt und getBytes ("UTF-16") aufgerufen und dann jedes der Bytes im Array gedruckt. Die Ausgabe war etwas verwirrend, da die ersten beiden Bytes 0xFFFFFFFE 0xFFFFFFFF waren, gefolgt von 0x00 0x52 0x00 0x6F. (Offensichtlich unterscheidet sich die Endianz hier von dem, was ich oben zu schaffen versuchte, aber das ist nicht wichtig).

diesen Ausgang verwenden ich beschlossen, meine Byte-Array die gleiche Art und Weise zu versuchen und zu erstellen:

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

Und es hat funktioniert seltsamerweise gut. Meine Frage ist also, warum Java erlaubt, dass ein ganzzahliger Wert von 0xFFFFFF80 oder größer automatisch in ein Byte ohne eine explizite Umwandlung umgewandelt wird, aber alles, was gleich oder größer als 0x80 ist, erfordert eine explizite Umwandlung?

Antwort

10

Der Schlüssel zu erinnern ist hier, dass int in Java ist ein vorzeichenbehafteter Wert. Wenn Sie 0xffffffff zuweisen (das ist 2^32 -1), wird dies in eine vorzeichenbehaftete int Wert -1 übersetzt - eine int kann nicht tatsächlich etwas so groß wie 0xffffffff als eine positive Zahl darstellen.

Also für Werte kleiner als 0x80 und größer als 0xFFFFFF80, der resultierende int Wert ist zwischen -128 und 127, die eindeutig als byte dargestellt werden können. Alles, was außerhalb dieses Bereichs liegt, kann nicht sein und muss mit einer expliziten Umwandlung gezwungen werden, wodurch Daten verloren gehen.

+0

Danke, das macht es viel klarer. – DaveJohnston

2

Wenn Sie eine Zahl ohne einen Hinweis (z. B. 1234L für eine lange) verwenden, nimmt der Compiler eine Ganzzahl an. Der Wert 0xffffffff ist eine Ganzzahl mit dem Wert -1, die ohne Warnung in byte umgewandelt werden kann.

+1

... weil Java die Zweierkomplement-Notation für negative Werte verwendet. – Ash

0

Da 0xffffffff ist die Zahl -1 und -1 kann als ein Byte interpretiert werden.

0

0xff ist das gleiche wie Schreiben 0x000000ff, nicht 0xffffffff. Das ist dein Problem. Die ganze Zahl ist eine positive Zahl (255), aber das Byte (wenn Bit für Bit konvertiert) wäre eine negative Zahl (-1). Aber 0xffffffff ist -1 sowohl als int als auch als byte.

0

Weil int signiert sind und 0xffffffff -1 repräsentieren und 0xff eine Ganzzahl von Wert 255 darstellen, die nicht in -128 (0x80) +127 (0x7f) Bereich eines Bytes liegen.