Объясните, чем логически является возвращаемое значение метода readInt()
из класса DataInputStream
?
В javadoc используется следующее объяснение принципа работы метода: пускай a-d являются первыми четырьмя байтами. Тогда метод вернет значение int
, эквивалентное:
(((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff))
Зачем тут используются конструкции вида байт & 0xFF
? Как изменяется исходный байт после логического умножения на восемь единиц? Насколько я помню, исходный байт не изменяется.
Непонятно, зачем используется конструкция вида байт | байт | байт | байт
. Для чего используется логическое ИЛИ?
Чем все-таки является возвращенный int
, склеенный из четырех байтов? Логически, это же совершенно другое число. Где обычно используется этот метод?
Ну давайте разбираться. Вот код этого метода из JDK 11.0.1 (полагаю, что он давно не менялся)
public final int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
Вначале тут идёт чтение четырёх байтов из InputStream
поля in
, которые записываются в переменные ch1
, ch2
, ch3
, ch4
. Тип этих переменных int
, потому что таков тип возвращаемого значения метода InputStream#read()
, несмотря на то, что на самом деле он возвращает лишь беззнаковый, то есть всегда положительный, байт в диапазоне 0..255. Тип int
для байта излишен, но за счёт этой излишести метод read()
может вернуть специальное значение -1
, которое означает попытку прочитать байт после окончания потока данных. Именно это и проверяется в выражении (ch1 | ch2 | ch3 | ch4) < 0
. Здесь производится операция ИЛИ
между всеми этими числами и проверяется, что результат меньше нуля, то есть, что самый левый бит равен единице. Произойти такое может только если хотя бы одна из этих переменных меньше нуля, то есть если хотя бы у одной из них самый левый бит равен единице. Если попытки чтения после окончания потока данных не было, то мы идём дальше, иначе бросаем исключение EOFException
. А дальше нам нужно построить int
из наших ch1
, ch2
, ch3
, ch4
, в каждом из которых по байту. Эти байты сдвигаются на соответствующие позиции и затем "склеиваются" сложением. С тем же успехом можно было бы использовать операцию ИЛИ
. Именно эта операция ИЛИ
используется в javadoc описании интерфейсного метода DataInput#readInt()
, вот так: (((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff))
. Операции число & 0xff
здесь излишни. Они обнуляют все биты левее младшего байта. Но поскольку мы прочитали байты они и так равны нулю.
В итоге мы получили обычный знаковый int
, прочитанный из четырёх байтов потока данных. Чтение происходит в порядке от старшего байта к младшему, называемом так же big-endian. Такой способ передачи данных используется при сериализации объектов Java, в протоколах TCP/IP, во многих форматах данных, например форматах изображения PNG, JPEG и прочих, в большенстве архитектур процессоров.
Существует так же обратый порядок, от младшего к старшему или little-endian. Им пользуются, например, Intel совместимые процессоры x86.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
программисты! Пытаюсь разобраться с контейнерамиПрограмма, используя метод add добавляет в массив из строк(изначально n=0 по размерности) заданное...
Есть дерево с какими-то элементамиЯ хочу, чтобы по нажатию на кнопку было можно изменить текст в выбранной ячейке