Я собираюсь начать работать над чем-то, требует байтов чтения и создания строк. Считанные байты представляют строки UTF-16. Таким образом, только для проверения вещей я хотел преобразовать простой массив байтов в кодировке UTF-16 к строке. Первые 2 байта в массиве должны представить порядок байтов и так должны быть или 0xff 0xfe или 0xfe 0xff. Таким образом, я пытался создать свой массив байтов следующим образом:
byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00};
Но я получил ошибку, потому что 0xFF и 0xFE являются слишком большими для вписывания в байт (потому что байты подписываются в Java). Более точно ошибка состояла в том, что интервал не мог быть преобразован в байт. Я знаю, что мог просто явно преобразовать от интервала до байта с броском и достигнуть желаемого результата, но это не то, о чем мой вопрос.
Только для испытания чего-то я создал Строку и звонил, getBytes ("UTF-16") тогда распечатал каждый из байтов в массиве. Вывод немного сбивал с толку, потому что первые два байта были 0xFFFFFFFE 0xFFFFFFFF, сопровождаемым 0x00 0x52 0x00 0x6F. (Obvisouly, порядок байтов здесь отличается от того, что я пытался создать выше, но это не важно).
Используя этот вывод я решил попытаться создать свой массив байтов тот же путь:
byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00};
И странно достаточно это хорошо работало. Таким образом, мой вопрос, почему Java позволяет целочисленное значение 0xFFFFFF80 или больше быть автоматически преобразованным в байт без явного броска, но что-нибудь равняется или больше, чем 0x80 требует явного броска?
Главное, что нужно запомнить, - это то, что int
в Java является значением со знаком. Когда вы назначаете 0xffffffff
(то есть 2 ^ 32 -1
), это преобразуется в знаковое int со значением -1
- int
не может на самом деле представлять такое большое число, как 0xffffffff
, как положительное число.
Таким образом, для значений меньше 0x80 и больше 0xFFFFFF80 результирующее значение int
находится в диапазоне от -128 до 127, что однозначно может быть представлено как байт
. Все, что находится за пределами этого диапазона, не может быть и требует принудительного выполнения явного приведения, что приводит к потере данных в процессе.
Если вы используете число без подсказки (например, 1234L для длинного числа), компилятор принимает целое число. Значение 0xffffffff
представляет собой целое число со значением -1
, которое может быть преобразовано в байт
без предупреждения.
0xff
то же самое, что и запись 0x000000ff
, а не 0xffffffff
. Так что это ваша проблема; целое число является положительным числом (255), но байт (при преобразовании бит в бит) будет отрицательным числом (-1). Но 0xffffffff
равно -1 и как int
, и как байт
.
Поскольку 0xffffffff - это число -1, а -1 можно интерпретировать как байт.
Поскольку int подписаны, а 0xffffffff представляет -1, а 0xff представляет собой целое число со значением 255, которое не находится в диапазоне байтов -128 (0x80) +127 (0x7f).