Главная страница

Ревью 5. Поток ввода объект, из которого можно считать данные. Поток вывода


Скачать 58.99 Kb.
НазваниеПоток ввода объект, из которого можно считать данные. Поток вывода
АнкорРевью 5
Дата24.05.2023
Размер58.99 Kb.
Формат файлаdocx
Имя файлаРевью 5.docx
ТипДокументы
#1156991

  1. Что такое потоки ввода-вывода? Как это реализовано в Java?


Поток ввода – объект, из которого можно считать данные.

Поток вывода – объект, в который можно записывать данные.
Байтовые: абстрактные классы:

- InputStream (представляющий потоки ввода);

- OutputStream (представляющий потоки вывода).
Для символов: абстрактные классы:

- Reader (для чтения потоков символов);

- Writer (для записи потоков символов).


  1. Что делает метод read?



Метод read() используется для чтения символов.
Данный метод возвращает кол-во только что прочитанных символов (целое число от 0 до 65635) или -1, если достиг конца потока(stream).

Почему он возвращает int а не byte. Почему он не может возвращать byte?
Он возвращает int, потому что диапазон byte в Java лежит от -128 до 127, а возвращаемое значение метода read() лежит в диапазоне от 0 до 255.
Чтобы получит представление byte в int, в методе read() используется побитовое "И" с числом 255, т.е убираются лидирующие единицы.
Что вернет метод read(), если он считывает файл и ему встречается байт равный -1?
Он вернет значение, к которому применилось побитовое "И" с числом 255. Т.е вернёт 255.


  1. Что такое System.in, что такое System.out?


System.in — это "стандартный" поток ввода и объект InputStream. Этот поток уже открыт и готов к подаче входных данных.

(например, ввод с клавиатуры или другому источнику ввода, заданные окружением хоста или пользователем).

System.out — это "стандартный" поток вывода и объект PrintStream. Этот поток уже открыт и готов к приему выходных данных.

Обычно этот поток соответствует выводу на дисплей или другому месту вывода, указанному окружением хоста или пользователем.


  1. Что делает flush? Почему важно закрывать потоки?


Flush очищает буфер и скидывает содержимое в поток.
При закрытии потока освобождаются все выделенные для него ресурсы, например, файл.

Если поток окажется не закрыт, может произойти утечка памяти.
Выполнится ли flush если мы сделаем close?
Да.

Вызывая close() на любом потоке java.io, автоматически вызывает flush().
Можно ли использовать flush() для небуферизированного потока и что будет?
Можно, среда хоста может выполнять свою собственную буферизацию, неизвестную Java. В этом случае запись можешь кэшироваться в буферах ОС).
Нужно ли закрывать Scanner? В каких случаях?
Если передавать System.in, то закрывать его не нужно.

Если передаем какой-то InputStream, связанный с файлом, сетевым ресурсом и т.п., то нужно закрывать.

Пере открыть закрытый Scanner соответственно не получится, потому что закрывается непосредственно stream.
Гарантируется ли запись данных в файл при вызове flush?
Не гарантирует.

flush() гарантирует только то, что байты, ранее записанные в поток, передаются операционной системе для записи.


  1. Расскажи про классы Reader и Writer?


Reader и Writer – это аналоги InputStream и OutputStream, но они работают с символами.
Иногда их еще называют символьными потоками, в противовес InputStream и OutputStream – байтовым потокам.

Reader – абстрактный класс, описывающий символьный ввод;

BufferedReader – буферизованный входной символьный поток;

CharArrayReader – входной поток, который читает из символьного массива;

FileReader – входной поток, читающий файл;

FilterReader – абстрактный класс, предоставляющий интерфейс для классов-надстроек;

InputStreamReader – входной поток, транслирующий байты в символы;

LineNumberReader – входной поток, подсчитывающий строки;

PipedReader – входной канал;

PushbackReader - входной поток, позволяющий возвращать символы обратно в поток;

StringReader - входной поток, читающий из строки.

Writer – абстрактный класс, описывающий символьный вывод;

BufferedWriter - буферизованный выходной символьный поток;

CharArrayWriter - выходной поток, который пишет в символьный массив;

FileWriter - выходной поток, пишущий в файл;

FilterWriter - абстрактный класс, предоставляющий интерфейс для классов-надстроек;

OutputStreamWriter - выходной поток, транслирующий байты в символы;

PipedWriter - выходной канал;

PrintWriter - выходной поток символов, включающий методы print() и println();

StringWriter - выходной поток, пишущий в строку;


  1. Как преобразовать считанные байты в символы? Какой класс для этого используется?


«мост» между классом OutputStream и классом Writer.

OutputStreamWriter – символы, записанные в поток, преобразовываются в байты.

InputStreamReader — аналог для чтения. При помощи методов класса Reader читаются байты из потока InputStream и далее преобразуются в символы.


  1. Отличие Scanner’a от BufferedReader’a?




Scanner

BufferedReader

используется для синтаксического анализа токенов из содержимого потока

просто считывает поток и не выполняет специального синтаксического анализа

Не синхронный

Синхронный




Имеет бОльшую буферную память (8192 символа)




  • Scanner скрывает IOException, BufferedReader бросает его немедленно;

  • Используйте Scanner, если хотите работать с несколькими потоками.


Есть у Сканнера буфер?
У сканера есть буфер, но он довольно маленький — всего 1024 символа.


  1. Отличие пакета io от nio?


IO потокоориентированный, а NIO буферо-ориентированный.
Потокоориентированный ввод/вывод подразумевает чтение/запись из потока/в поток одного или нескольких байт в единицу времени поочередно.
У NIO буферо-ориентированный – данные считываются в буфер для последующей обработки.



io

nio

Потокоориентированный

Буфер-ориентирванный

Блокирующий (синхронный) ввод/вывод

Неблокирующий (асинхронный) ввод/вывод




Селекторы



  1. Расскажи про класс File? Как создать новый файл на жестком диске?


Класс File (пакет java.io), не работает напрямую с потоками. Он управляет информацией о файлах и каталогах.
Создать файл вызовом метода createNewFile().

file.createNewFile();
Создать файл в Java с помощью объекта File можно тремя способами:
1. Передав в объект абсолютный путь

2. Указать только имя файла

3. Указать относительный путь
Методы

createNewFile() - создает новый файл по пути, который передан в конструкторе;

delete() - удаляет каталог или файл по пути, который передан в конструкторе;

exists() - проверяет, существует ли по указанному в конструкторе пути файл или каталог;

getAbsolutePath() - возвращает абсолютный путь для пути, который передан в конструктор;

getName() - возвращает краткое имя файла или каталога;

length() - возвращает размер файла в байтах;

mkdir() - создает новый каталог и при удачном создании возвращает значение true.


  1. В чём отличие File от Path?


File - класс, самая старая версия работы с папками и файлами.

Его методы возвращают тру/фолс.
Path - интерфейс, более новый, его методы выбрасывают исключение в случае проблем.
Path допускает работу с файлами на виртуальных файловых системах, а File нет.

  1. В чем разница между абсолютным и относительным путем?


Абсолютный путь начинается с корневой директории (всегда содержит корневой элемент и полный список каталогов, для нахождения файла.)
Относительный путь считается относительно какой-то директории. Т.е. это как бы конец пути, но только без начала (необходимо соединить с другим путем, чтобы получить доступ к файлу).
Относительный путь можно превратить в абсолютный и наоборот.


  1. Что такое клонирование? Как реализовано клонирование в Java?


Клонирование – создание объекта на основе уже существующего.
Клонировать объект в Java можно тремя способами:

1. Переопределение метода clone() и реализация интерфейса Cloneable;

2. Использование конструктора копирования;

3. Использовать для клонирования механизм сериализации.


  1. Как удалить директорию с файлами?


Чтобы удалить директорию с файлами, сначала необходимо удалить сами файлы в папке, а затем и саму папку.
Необходимо воспользоваться методом delete(Path path) класса Files.

Пример кода: Files.delete(Path.of(“c:\\desktop);
Директория будет удалена, только если она пустая.

Вложенные директории удаляются с помощью рекурсии.



  1. В чём разница между поверхностным и глубоким клонированием? Как реализовать глубокое клонирование?


Поверхностное копирование: копирует настолько маленькую часть, насколько это возможно. По умолчанию, копирование в Java является поверхностным, т.е Object class не знает о структуре класса, которого он копирует.

- Если класс имеет только члены примитивных типов, то будет создана совершенно новая копия объекта и возвращена ссылка на этот объект.

- Если класс содержит не только члены примитивных типов, а и любого другого типа класса, тогда копируются ссылки на объекты этих классов. Следовательно, оба объекта будут иметь одинаковые ссылки.
Глубокое копирование. Мы создаем клон, который не зависит от исходного объекта, и внесение изменений в клонированный объект не должно влиять на исходный объект.

Глубокое копирование — это две коллекции, в одну из которых дублируются все элементы оригинальной коллекции. Мы хотим сделать копию, при которой внесение любых изменений в копию не затронет оригинальную коллекцию.
Как реализовать глубокое клонирование?
Глубокое клонирование требует выполнения следующих правил:

  • Нет необходимости копировать отдельно примитивные данные;

  • Все классы-члены в оригинальном классе должны поддерживать клонирование. Для каждого члена класса должен вызываться super.clone() при переопределении метода clone();

  • Если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному.





  1. Что такое сериализация и десериализация?


Сериализация – процесс сохранения состояния объекта в последовательность байт.
Десериализация – процесс восстановления объекта из этих байт.
Любой Java объект можно преобразовать в последовательность байт. Чтобы появилась возможность сериализовать объект, он должен наследовать интерфейс Serializable.
Данный интерфейс не имеет каких-либо методов, а просто дает понять системе, что объект, который реализует его, может быть сериализован.
Для сериализации объектов в поток используется класс ObjectOutputStream. Он записывает данные в поток.

Для десериализации используется класс ObjetInputStream
Можно ли сериализовать и десериализовать final переменную с помощью Externalizable?



  1. Назовите несколько форматов сериализации.


Основные форматы сериализации:

JSON YAML XML BSON


  1. Какие поля не сериализуются?


Поля класса, помеченные модификатором transient(трЭнзиент), не сериализуются.


  1. Как сериализовать статическое поле?


Реализовать интерфейс Externalizable(Экстэнализабл) тогда сериализовать и десериализовать статическое поле можно, но не рекомендуется этого делать, т.к. это может сопровождаться трудноуловимыми ошибками.

При стандартной сериализации, поля с модификатором static не сериализуются. Соответственно, после десериализации это поле значение не поменяет.


  1. Чем отличается сериализация Serializable от Еxternalizable?


При записи Serializable класса весь контроль над сериализацией достается JVM

Интерфейс Externalizable расширяет Serializable и добавляет методы записи и чтения writeExternal и readExternal.

Этот интерфейс позволяет реализовать полностью свой механизм сериализации, стандартно запишется только идентификатор класса. Никакой автоматической работы с классом-родителем также не предусмотрено. Методы readObject и writeObject игнорируются. Ключевое слово transient эффекта на Externalizable не имеет.
Externalizable объект в отличие от Serializable десерализуется не в обход конструктора, так что должен иметь конструктор без аргументов.


написать администратору сайта