Ответ 1
Как говорится в трояном, ваше замешательство в результатах вашего кода частично связано с расширением знака. Я попытаюсь добавить более подробное объяснение, которое может помочь с вашей путаницей.
char a = '\uffff';
byte b = (byte)a; // b = 0xFF
Как вы отметили, это приводит к потере информации. Это считается сужение конверсии. Преобразование char в байт "просто отбрасывает все, кроме n бит младшего разряда".
Результат: 0xFFFF -> 0xFF
char c = (char)b; // c = 0xFFFF
Преобразование байта в char считается специальным преобразованием . Он фактически выполняет ДВА преобразования. Во-первых, байт является расширенным SIGN (новые биты верхнего порядка копируются из старого знакового бита) в int (нормальное расширяющееся преобразование). Во-вторых, int преобразуется в char с сужением преобразования.
Результат: 0xFF -> 0xFFFFFFFF -> 0xFFFF
int d = (int)c; // d = 0x0000FFFF
Преобразование a char в int считается расширяющимся преобразованием. Когда тип char расширяется до интегрального типа, он имеет ZERO-расширение (новые биты старшего порядка равны 0).
Результат: 0xFFFF -> 0x0000FFFF
. При печати это даст вам 65535.
Три приведенные мной ссылки являются официальными данными спецификации языка Java для примитивных типов преобразований. Я ВЫ рекомендую вам взглянуть. Они не являются ужасно подробными (и в этом случае относительно простыми). Он точно определяет, что java будет делать за кулисами с преобразованием типов. Это общая область недопонимания для многих разработчиков. Опубликуйте комментарий, если вы все еще путаетесь с любым шагом.