Char в байт?(Джава) - PullRequest
       39

Char в байт?(Джава)

15 голосов
/ 10 февраля 2011

Как это происходит:

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?

По сути, я видел, что char является 16-разрядным.Следовательно, если вы преобразуете его в byte, почему данные не теряются?(Значение остается тем же после преобразования в int)

Заранее спасибо за ответ на этот мой маленький невежественный вопрос.: P

РЕДАКТИРОВАТЬ: Woah, обнаружил, что мой исходный вывод на самом деле сделал, как ожидалось, но я только что обновил код выше.По сути, символ преобразуется в байт, а затем возвращается в символ, и его первоначальное 2-байтовое значение сохраняется.Как это происходит?

Ответы [ 4 ]

24 голосов
/ 10 февраля 2011

Как заявляет trojanfoe, ваша путаница с результатами вашего кода частично связана с расширением знака. Я постараюсь добавить более подробное объяснение, которое может помочь в вашей путанице.

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

Как вы заметили, это приводит к потере информации. Это считается сужающим преобразованием . Преобразование символа в байт «просто отбрасывает все, кроме n младших битов».
Результат: 0xFFFF -> 0xFF

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

Преобразование байта в символ считается специальным преобразованием . Он фактически выполняет ДВЕ преобразования. Во-первых, байт является расширенным SIGN (новые биты старшего разряда копируются из старого битового знака) в int (нормальное расширяющее преобразование). Во-вторых, int преобразуется в символ с сужающимся преобразованием.
Результат: 0xFF -> 0xFFFFFFFF -> 0xFFFF

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

Преобразование символа в int считается расширяющимся преобразованием . Когда тип char расширяется до целочисленного типа, он расширяется нулями (новые биты старшего разряда устанавливаются в 0).
Результат: 0xFFFF -> 0x0000FFFF. При печати это даст вам 65535.

Три ссылки, которые я предоставил, являются официальными подробностями Спецификации языка Java о примитивных преобразованиях типов. Я настоятельно рекомендую вам взглянуть. Они не очень многословны (и в этом случае относительно просты). Он подробно описывает, что будет делать Java за кулисами при преобразовании типов Это общая область недопонимания для многих разработчиков. Оставьте комментарий, если вы все еще не понимаете какой-либо шаг.

8 голосов
/ 10 февраля 2011

Это расширение знака . Попробуйте \u1234 вместо \uffff и посмотрите, что получится.

5 голосов
/ 10 февраля 2011

Java byte подписано. это противоречит интуиции. почти во всех ситуациях, когда используется байт, программисты хотели бы использовать байт без знака. это очень вероятно ошибка, если байт приведен к int напрямую.

Это правильно выполняет конвертирование почти во всех программах:

int c = 0xff & b ;

Эмпирически, выбор подписанного байта является ошибкой.

0 голосов
/ 10 февраля 2011

Некоторые довольно странные вещи, происходящие на вашей машине. Взгляните на спецификацию языка Java, глава 4.2.1 :

Значения целочисленных типов целые числа в следующих диапазонах:

для байтов, от -128 до 127 включительно

... обрезать других ...

Если ваша JVM соответствует стандартам, то ваш вывод должен быть -1.

...