В Java int
составляет 32 бита. A byte
составляет 8 bits
.
Большинство примитивных типов в Java подписаны, а byte
, short
, int
и long
кодируются в дополнение к двум. (Тип char
является беззнаковым, и понятие знака неприменимо к boolean
.)
В этой числовой схеме старший значащий бит указывает знак числа. Если требуется больше битов, самый старший бит («MSB») просто копируется в новый MSB.
Итак, если у вас есть байт 255
: 11111111
и вы хотите представить его как int
(32 бита), просто скопируйте 1 влево 24 раза.
Теперь, один из способов прочитать отрицательное число дополнения до двух - начать с наименее значимого бита, двигаться влево до тех пор, пока не найдете первую 1, а затем инвертировать каждый бит. Полученное число является положительной версией этого числа
Например: 11111111
переходит на 00000001
= -1
. Это то, что Java будет отображать в качестве значения.
То, что вы, вероятно, хотите сделать, это знать беззнаковое значение байта.
Вы можете сделать это с помощью битовой маски, которая удаляет все, кроме наименее значимых 8 бит. (0xff)
Итак:
byte signedByte = -1;
int unsignedByte = signedByte & (0xff);
System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);
распечатал бы: "Signed: -1 Unsigned: 255"
Что на самом деле здесь происходит?
Мы используем побитовое И, чтобы замаскировать все посторонние знаковые биты (1 слева от младших 8 бит).
Когда int преобразуется в байт, Java отсекает самые левые 24 бита
1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101
Поскольку 32-й бит теперь является знаковым битом, а не 8-м битом (и мы устанавливаем бит знака в 0, который является положительным), исходные 8 бит из байта считываются Java как положительное значение.