Java неявное преобразование int в байт - PullRequest
9 голосов
/ 20 декабря 2009

Я собираюсь начать работать над чем-то, что требует чтения байтов и создания строк. Читаемые байты представляют строки UTF-16. Так что просто для проверки я хотел преобразовать простой байтовый массив в кодировке UTF-16 в строку. Первые 2 байта в массиве должны представлять порядковый номер и должны быть 0xff 0xfe или 0xfe 0xff. Поэтому я попытался создать свой байтовый массив следующим образом:

byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00};

Но я получил ошибку, потому что 0xFF и 0xFE слишком велики, чтобы вписаться в байт (потому что байты подписаны в Java). Точнее, ошибка заключалась в том, что int нельзя преобразовать в байт. Я знаю, что мог бы просто явно преобразовать int в байт с помощью приведения и достичь желаемого результата, но это не то, о чем мой вопрос.

Просто чтобы попробовать что-то, я создал String и вызвал getBytes ("UTF-16"), а затем напечатал каждый из байтов в массиве. Вывод был немного запутанным, потому что первые два байта были 0xFFFFFFFE 0xFFFFFFFF, а затем 0x00 0x52 0x00 0x6F. (Obvisouly здесь порядок байтов отличается от того, что я пытался создать выше, но это не важно).

Используя этот вывод, я решил попытаться создать свой байтовый массив так же:

byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00};

И как ни странно, все работало нормально. Поэтому у меня вопрос: почему Java допускает автоматическое преобразование целого значения 0xFFFFFF80 в байт без явного преобразования, но для любого значения, равного или превышающего 0x80, требуется явное приведение?

Ответы [ 5 ]

10 голосов
/ 20 декабря 2009

Ключевым моментом, который следует помнить здесь, является то, что int в Java - это значение со знаком. Когда вы присваиваете 0xffffffff (то есть 2^32 -1), это переводится в целое число со знаком -1 - int не может фактически представлять что-то такое большое, как 0xffffffff как положительное число.

Таким образом, для значений менее 0x80 и более 0xFFFFFF80 результирующее значение int находится в диапазоне от -128 до 127, что однозначно можно представить как byte. Ничего за пределами этого диапазона не может быть и требует принудительного явного приведения, потери данных в процессе.

2 голосов
/ 20 декабря 2009

Если вы используете число без подсказки (например, 1234L для длинной строки), компилятор принимает целое число. Значение 0xffffffff является целым числом со значением -1, которое может быть приведено к byte без предупреждения.

0 голосов
/ 20 декабря 2009

Поскольку int имеют значение со знаком и 0xffffffff представляют -1, а 0xff представляют целое число со значением 255, которое не лежит в диапазоне байтов -128 (0x80) +127 (0x7f).

0 голосов
/ 20 декабря 2009

0xff - это то же самое, что и запись 0x000000ff, а не 0xffffffff. Так что это ваша проблема; целое число - это положительное число (255), но байт (если преобразован бит за битом) будет отрицательным числом (-1). Но 0xffffffff равно -1 как int, так и byte.

0 голосов
/ 20 декабря 2009

Поскольку 0xffffffff - это число -1, а -1 можно интерпретировать как байт.

...