Как же все-таки устроена работа метода read()
:
int
а не byte
?byte
как int
в диапазоне от 0 до 255?byte
?read
класса InputStream
возвращает int
, а не byte
Попробуйте выполнить такой код:
byte myByte = -3; // 11111101
byte[] myArray = {myByte};
InputStream in = new ByteArrayInputStream(myArray);
int myInt = in.read();
System.out.println(myInt); // 253
В консоль выводится 253, а не -3.
Почему так происходит?
Тип данных int в Java является дополненнным до двух целым числом и использует 32 бита вместо 8.
В 32х битном виде число 253 будет:
00000000000000000000000011111101
т. е. метод read() возвращает не само значение byte, а его представление в 32х битном виде.
int
в byte
| число | 32 bit | 8 bit |
----- -------------------------------- --------
| . . | . . . . . . . . . . . . . . . . |
| . . | . . . . . . . . . . . . . . . . |
| -128 | 11111111111111111111111110000000 | 10000000 |
| -127 | 11111111111111111111111110000001 | 10000001 |
| -126 | 11111111111111111111111110000010 | 10000010 |
| -125 | 11111111111111111111111110000011 | 10000011 |
| . . | . . . . . . . . . . . . . . . . | . . . . |
| . . | . . . . . . . . . . . . . . . . | . . . . |
| -2 | 11111111111111111111111111111110 | 11111110 |
| -1 | 11111111111111111111111111111111 | 11111111 |
| 0 | 00000000000000000000000000000000 | 00000000 |
| 1 | 00000000000000000000000000000001 | 00000001 |
| 2 | 00000000000000000000000000000010 | 00000010 |
| . . | . . . . . . . . . . . . . . . . | . . . . |
| . . | . . . . . . . . . . . . . . . . | . . . . |
| 125 | 00000000000000000000000001111101 | 01111101 |
| 126 | 00000000000000000000000001111110 | 01111110 |
| 127 | 00000000000000000000000001111111 | 01111111 |
| . . | . . . . . . . . . . . . . . . . |
| . . | . . . . . . . . . . . . . . . . |
Диапазон byte в Java лежит от -128 до 127, а возвращаемое значение метода read() лежит в диапазоне от 0 до 255.
byte
в методе read
Чтобы получить представление byte в int в методе read() используется побитовое «И» c числом 255, т. е. убираем лидирующие единицы.
| число | 32 bit |
----- --------------------------------
| -3 | 11111111111111111111111111111101 |
И
| 255 | 00000000000000000000000011111111 |
=
| 253 | 00000000000000000000000011111101 |
Чтобы из представления получить обратно значение byte в int, нужно выполнить обратную операцию побитовое «ИЛИ» c числом -256, т. е. добавляем лидирующие единицы.
| число | 32 bit |
----- --------------------------------
| 253 | 00000000000000000000000011111101 |
ИЛИ
| -256 | 11111111111111111111111100000000 |
=
| -3 | 11111111111111111111111111111101 |
byte == -1
в методе read()
То же самое: убираем лидирующие единицы.
| число | 32 bit |
----- --------------------------------
| -1 | 11111111111111111111111111111111 |
И
| 255 | 00000000000000000000000011111111 |
=
| 255 | 00000000000000000000000011111111 |
На все 4 вопроса вообще один ответ. Возвращается int
потому что надо такой тип, который может вместить в себя один байт (реальные данные) плюс одно служебное значение (это тот самый -1
), которое является признаком окончания чтения.
Вообще конечно можно бы было спроектировать метод read() так, чтобы он возвращал byte
. Но тогда этот метод в случае окончания потока либо должен был бросать исключение, либо вводить допольнительный метод, при помощи которого бы можно было проверять окончание потока. С обоими способами бы были проблемы, т.к. с исключениями у программистов всегда бы оно ловилось, а природа исключений немного другая. А с дополнительным методом нельзя заставить обязать программиста его везде вызывать (ведь если этот вызов будет опущен, то как отделить, когда из потока методом read
возращается 0
с данными от 0
когда данных нет.
Вообще говоря, этот метод редко используется, в основном из-за своих проблем с производительностью. Предпочтение отдаётся методу read(byte[]), который читает сразу массив байт.
P.S. Другой вопрос почему тут выбрали int
, а не short
. Точных причин сказать не могу, но скорее потому, что short
считается неполноценным братом int
. Многие арифметические алгоритмы предпочитают использовать всегда int
, даже когда точно известно, что диапазона short
вполне хватит. И ещё есть момент с short
. JVM-инструкции более заточены на int
, нежели на short
.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Я разрабатываю приложение под Android и хотел бы узнать как реализовать сервер который бы принимал данные и сохранял их в базу данных желательно...
Основное задание заключается в том, что б поменять местами столбики в csv файлеЯ выгрузила их оттуда в матрицу, написала цикл с заменой столбиков,...
Чем отличаются методы от конструкторов в java? Для чего нужно то и другое?
Очень странные вещи происходят