Подтвердить что ты не робот

Преобразование байтов и char в Java

Если я преобразую символ в byte, а затем обратно в char, этот персонаж загадочно исчезает и становится чем-то другим. Как это возможно?

Это код:

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

До строки 2 все в порядке:

  • В строке 1 я могу напечатать "a" в консоли, и он отобразит "È".

  • В строке 2 я могу напечатать "b" в консоли, и будет показано -56, то есть 200, потому что байт подписан. А 200 - "È". Так что все еще хорошо.

Но что неправильно в строке 3? "c" становится чем-то другим, и программа печатает ? 65480. Это нечто совершенно другое.

Что я должен написать в строке 3, чтобы получить правильный результат?

4b9b3361

Ответ 1

Символ в Java - это код кода Unicode, который обрабатывается как беззнаковое число. Поэтому, если вы выполняете c = (char)b, вы получаете 2 ^ 16 - 56 или 65536 - 56.

Или, точнее, байт сначала преобразуется в целое число со знаком со значением 0xFFFFFFC8 с использованием расширения знака в расширяющемся преобразовании. Это, в свою очередь, затем сужается до 0xFFC8 при отливке на a char, что переводит на положительное число 65480.

Из спецификации языка:

5.1.4. Расширение и сужение примитивного преобразования

Сначала байт преобразуется в int посредством расширения примитивного преобразования (п. 5.1.2), и затем полученный int преобразуется в char путем сужения примитивного преобразования (§5.1.3).


Чтобы получить правильную точку, используйте char c = (char) (b & 0xFF), которая сначала преобразует значение байта b в положительное целое число 200 с помощью маски, обнуляя верхние 24 бита после преобразования: 0xFFFFFFC8 становится 0x000000C8 или положительное число 200 по десятичным знакам.


Выше приведено прямое объяснение того, что происходит при конверсии между примитивными типами byte, int и char.

Если вы хотите кодировать/декодировать символы из байтов, используйте Charset, CharsetEncoder, CharsetDecoder или один из удобных методов, таких как new String(byte[] bytes, Charset charset) или String#toBytes(Charset charset). Вы можете получить набор символов (например, UTF-8 или Windows-1252) из ​​StandardCharsets.