for (int i=0; i <= 255; i++) {
byte b = (byte) i; // cast int values 0 to 255 to corresponding byte values
int neg = b; // neg will take on values 0..127, -128, -127, ..., -1
int pos = (int) (b & 0xFF); // pos will take on values 0..255
}
Преобразование байта, который содержит значение больше 127 (т.е. значения от 0x80 до 0xFF), в int приводит к расширению знака старшего бита значения байта (то есть, бит 0x80). Чтобы удалить лишние биты, используйте x & 0xFF; это устанавливает биты выше 0x80 (то есть биты 0x100, 0x200, 0x400, ...) в ноль, но оставляет младшие 8 битов как есть.
Вы также можете написать это; все они эквивалентны:
int pos = ((int) b) & 0xFF; // сначала конвертируем b в int, затем отбрасываем старшие биты
int pos = b & 0xFF; // сделано как арифметика int - приведение не требуется
Java автоматически «продвигает» целочисленные типы, размер которых (в # битах) меньше, чем int, к значению int при выполнении арифметики. Это сделано для обеспечения более детерминированного результата (чем, скажем, C, который менее ограничен в своей спецификации).
Возможно, вы захотите взглянуть на на этот вопрос, когда ставите «шорт».