Char в байт? (Ява)

Как так получилось:

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)

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

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


person wakachamo    schedule 10.02.2011    source источник
comment
Да, только что понял, что и у меня тоже. Тем не менее, я обновил приведенный выше код, и теперь, по сути, символ преобразуется в байт, а затем возвращается в char, и его исходное 2-байтовое значение сохраняется. Как это произошло?   -  person wakachamo    schedule 10.02.2011


Ответы (4)


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

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

Как вы отметили, это ДЕЙСТВИТЕЛЬНО приводит к потере информации. Это считается сужающим преобразованием < / а>. Преобразование символа в байт "просто отбрасывает все, кроме n младших битов".
Результат: 0xFFFF -> 0xFF

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

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

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

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

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

person robert_x44    schedule 10.02.2011

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

person trojanfoe    schedule 10.02.2011

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

Это делает предполагаемое преобразование правильно почти во всех программах:

int c = 0xff & b ;

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

person irreputable    schedule 10.02.2011

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

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

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

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

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

person darioo    schedule 10.02.2011