Беззнаковые байты в Java
Байты в Java подписаны по умолчанию. Я вижу на других сообщениях, что обходной путь для беззнаковых байтов аналогичен таковому: int num = (int) bite & 0xFF
Может кто-нибудь объяснить мне, почему это работает и преобразует подписанный байт в беззнаковый байт, а затем его соответствующее целое число? ANDing
байт с 11111111 приводит к тому же байту - правильно?
Ответы
Ответ 1
Признак типа имеет более высокий приоритет, чем оператор &
. Поэтому вы сначала бросаете int, а затем ANDing, чтобы замаскировать все установленные старшие биты, включая "знаковый бит" из двух дополнений, которые использует java, оставляя вам только положительное значение исходный байт. Например:.
let byte x = 11111111 = -1
then (int) x = 11111111 11111111 11111111 11111111
and x & 0xFF = 00000000 00000000 00000000 11111111 = 255
и вы эффективно удалили знак из исходного байта.
Ответ 2
Инициализация байта с 11111111 приводит к тому же байту - правильно?
За исключением AND AND с 00000000000000000000000011111111, потому что 0xFF является литералом int
- в Java нет литералов byte
. Итак, что происходит, это то, что byte
продвигается до int
(тип не нужен), имеет расширенный знак (т.е. Сохраняет возможное отрицательное значение byte
), но затем расширение знака отменяется с помощью ANDing with with все эти нули. Результатом является int
, который имеет как наименее значащие биты в точности предыдущий byte
, и, следовательно, значение byte
было бы без знака.
Ответ 3
В Java 8 такой метод появился в классе Byte:
/**
* Converts the argument to an {@code int} by an unsigned
* conversion. In an unsigned conversion to an {@code int}, the
* high-order 24 bits of the {@code int} are zero and the
* low-order 8 bits are equal to the bits of the {@code byte} argument.
*
* Consequently, zero and positive {@code byte} values are mapped
* to a numerically equal {@code int} value and negative {@code
* byte} values are mapped to an {@code int} value equal to the
* input plus 2<sup>8</sup>.
*
* @param x the value to convert to an unsigned {@code int}
* @return the argument converted to {@code int} by an unsigned
* conversion
* @since 1.8
*/
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
Ответ 4
Как вы видите, результат int
не байт
Как это работает, скажем, у нас есть byte b = -128;
, это представлено как 1000 0000
, так что происходит, когда вы выполняете свою линию? Позвольте использовать temp int для этого, скажем:
int i1 = (int)b;
i1 теперь -128, и это фактически представлено в двоичном виде следующим образом:
1111 1111 1111 1111 1111 1111 1000 0000
Итак, как выглядит i1 & 0xFF
в двоичном формате?
1111 1111 1111 1111 1111 1111 1000 0000
&
0000 0000 0000 0000 0000 0000 1111 1111
что приводит к
0000 0000 0000 0000 0000 0000 1000 0000
и это ровно 128, то есть ваше подписанное значение преобразуется в unsigned.
Edit
Конвертированный байт -128 .. 127
в 0 .. 255
int unsignedByte = 128 + yourByte;
Вы не можете представлять значения с 128 по 255 с помощью байта, вы должны использовать что-то еще, например, int или smallint.
Ответ 5
Да, но таким образом вы можете быть уверены, что никогда не получите число > 255 или < 0.
Если первый бит равен 1, число отрицательно. Если вы конвертируете байт в int, если он отрицательный, он будет предварительно забит 1 байт, а если положительный - с 0 байтами. Запуск и процедура сбросят все байты слева от первого 8. Это фактически добавит 256 к отрицательным байтам.