Znak na bajt? (Java)

Jak to się dzieje:

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?

W zasadzie widziałem, że char jest 16-bitowy. Dlatego, jeśli wrzucisz go do byte, Jak to możliwe, że żadne dane nie zostaną utracone? (Wartość jest taka sama po wrzuceniu do int)

Z góry dziękuję za odpowiedź na moje małe, ignoranckie pytanie. : P

EDIT: Woah, dowiedziałem się, że mój oryginalny wynik rzeczywiście zrobił zgodnie z oczekiwaniami, ale właśnie zaktualizowałem powyższy kod. Zasadniczo znak jest wrzucany do bajtu, a następnie z powrotem do znaku, a jego oryginalna, 2-bajtowa wartość jest zachowana. Jak to się stało?

Author: wakachamo, 2011-02-10

4 answers

Jak twierdzi trojanfoe, Twoje zamieszanie w wynikach Twojego kodu jest częściowo spowodowane rozszerzeniem znaku. Postaram się dodać bardziej szczegółowe wyjaśnienie, które może pomóc w zamieszaniu.

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

Jak zauważyłeś, powoduje to utratę informacji. Jest to uważane za konwersję zwężającą . Konwersja znaku na bajt "po prostu odrzuca wszystkie bity niż n najniższego rzędu".
Wynik to: 0xFFFF -> 0xFF

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

Konwersja bajtu na znak jest uważana za specjalna konwersja . W rzeczywistości wykonuje dwie konwersje. Po pierwsze, bajt jest rozszerzany znakiem (nowe bity wysokiego rzędu są kopiowane ze starego bitu znaku) do int (normalna konwersja rozszerzająca). Po drugie, int jest konwertowany na znak z konwersją zwężającą.
Wynik to: 0xFF -> 0xFFFFFFFF -> 0xFFFF

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

Konwersja znaku na int jest uważana za konwersję rozszerzającą . Gdy typ znaku jest rozszerzony do typu całkowego, jest on rozszerzony o ZERO (nowe bity wysokiego rzędu są Ustaw na 0).
Wynikiem jest: 0xFFFF -> 0x0000FFFF. Po wydrukowaniu otrzymasz 65535.

Trzy linki, które podałem, to oficjalne szczegóły specyfikacji języka Java dotyczące prymitywnych konwersji typów. Gorąco polecam zajrzeć. Nie są strasznie gadatliwe (i w tym przypadku stosunkowo proste). Opisuje dokładnie, co java będzie robić za kulisami z konwersjami typów. Jest to częsty obszar nieporozumień dla wielu programistów. Dodaj komentarz, jeśli nadal jesteś mylony z każdym krokiem.

 30
Author: robert_x44,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-08 16:12:14

To Rozszerzenie znaku . Spróbuj \u1234 zamiast \uffff i zobacz, co się stanie.

 8
Author: trojanfoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-10 15:03:28

Java {[1] } jest podpisana. jest intuicyjny. w prawie wszystkich sytuacjach, w których używany jest bajt, Programiści chcieliby zamiast niego bajt niepodpisany. jest to bardzo prawdopodobne błąd, jeśli bajt jest rzucany bezpośrednio do int.

To poprawnie wykonuje zamierzoną konwersję w prawie wszystkich programach:

int c = 0xff & b ;

Empirycznie, wybór podpisanego bajtu jest błędem.

 6
Author: irreputable,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-10 15:18:20

Coś dziwnego dzieje się na Twojej maszynie. Spójrz na specyfikację języka Java, rozdział 4.2.1:

Wartości typów całkowych są liczby całkowite w następujących przedziałach:

Dla bajtów, od -128 do 127, włącznie

... wyciąć innych...

Jeśli twój JVM jest zgodny ze standardami, to twoje wyjście powinno być -1.

 0
Author: darioo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-10 15:10:50