Главная страница
Навигация по странице:

  • КЛОНИРОВАНИЕ И КОПИРОВАНИЕ

  • СЕРИАЛИЗАЦИЯ И ДЕСЕРИАЛИЗАЦИЯ

  • 5 блок. Вводвывод, доступ к файловой системе


    Скачать 270.29 Kb.
    Название5 блок. Вводвывод, доступ к файловой системе
    Дата03.09.2022
    Размер270.29 Kb.
    Формат файлаdocx
    Имя файлаJava 5 module.docx
    ТипДокументы
    #660115
    страница3 из 3
    1   2   3
    Класс File и интерфейс Path

    1. В чем отличия java.io.File и java.nio.file.Path?

    File — это класс, Path — это интерфейс.

    File — это старый способ доступа к файловой системе, Path — это новый рекомендуемый способ.

    Path более стройный, в нём нет булевских флажков, методы бросают исключения, можно работать с расширенными атрибутами файлов, например с правами доступа или с символическими ссылками, создавать их или узнавать куда ссылка ведёт. В Path появились методы перемещения и копирования файлов

    Path допускает работу с файлами на виртуальных файловых системах, а File нет.

    2. Конструкторы и методы класса File?

    В отличие от большинства классов ввода/вывода, класс File работает не с потоками, а непосредственно с файлами. Данный класс позволяет получить информацию о файле: права доступа, время и дата создания, путь к каталогу. А также осуществлять навигацию по иерархиям подкаталогов.
    Конструкторы класса File:

    File(String path) - указывается путь к файлу

    File(File dir, String name) - указывается объекта класса File (каталог) и имя файла

    File(String dirPath, Sring name) - указывается путь к файлу и имя файла

    File(URI uri) - указывается объекта URI, описывающий файл.
    Методы класса File:

    getAbsolutePath() - абсолютный путь файла, начиная с корня системы.

    canRead() - доступно для чтения

    canWrite() - доступно для записи

    exists() - файл существует или нет

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

    getParent() - возвращает имя родительского каталога

    getPath() - путь

    lastModified() - дата последнего изменения

    isFile() - объект является файлом, а не каталогом

    isDirectory()- объект является каталогом

    isAbsolute() - возвращает true, если файл имеет абсолютный путь

    renameTo(File newPath) - переименовывает файл. В параметре указывается имя нового имени файла. Если переименование прошло неудачно, то возвращается false

    delete() - удаляет файл. Также можно удалить пустой каталог

    3. Методы интерфейса Path

    - compareTo(Path other) - Сравнивает два абстрактных пути лексикографически.

    - endsWith(Path other) - Тесты, если этот путь заканчивается данным путем.

    - endsWith(String other) - Тесты, если этот путь заканчивается a Path, созданный, преобразовывая данную строку пути, точно способом, определенным endsWith(Path) метод.

    - equals(Object other) - Тесты этот путь для равенства с данным объектом.

    - getFileName() - Возвращает имя файла или каталога, обозначенного этим путем как a Path объект.

    - getFileSystem() - Возвращает файловую систему, которая создала этот объект.

    - getName(int index) - Возвращает элемент имени этого пути как a Path объект.

    - getNameCount() - Возвращает число элементов имени в пути.

    - getParent() - Возвращает родительский путь, или null если у этого пути нет родителя.

    - getRoot() - Возвращает корневой компонент этого пути как a Path объект, или null если у этого пути нет корневого компонента.

    - hashCode() - Вычисляет хэш-код для этого пути.

    - isAbsolute() - Говорит, является ли этот путь абсолютным.

    - iterator() - Возвращает iterator по элементам имени этого пути.

    - normalize() - Возвращает путь, который является этим путем с избыточными устраненными элементами имени.

    - register(WatchService watcher, WatchEvent.Kind... events) - Регистрирует файл, расположенный этим путем со службой часов.

    - register(WatchService watcher, WatchEvent.Kind[] events, WatchEvent.Modifier... modifiers) - Регистрирует файл, расположенный этим путем со службой часов.

    - relativize(Path other) - Создает относительный путь между этим путем и данным путем.

    - resolve(Path other) - Разрешите данный путь против этого пути.

    - resolve(String other) - Преобразовывает данную строку пути в a Path и решения это против этого Path точно способом, определенным resolve метод.

    - resolveSibling(Path other) - Разрешает данный путь против этого пути parent путь.

    - resolveSibling(String other) - Преобразовывает данную строку пути в a Path и решения это против этого пути - - parent путь точно способом, определенным resolveSibling метод.

    - startsWith(Path other) - Тесты, если этот путь запускается с данного пути.

    - startsWith(String other) - Тесты, если этот путь запускается с a Path, созданный, преобразовывая данную строку пути, точно способом, определенным startsWith(Path) метод.

    - subpath(int beginIndex, int endIndex) - Возвращает родственника Path это - подпоследовательность элементов имени этого пути.

    - toAbsolutePath() - Возвраты a Path объект, представляющий абсолютный путь этого пути.

    - toFile() - Возвраты a File объект, представляющий этот путь.

    - toRealPath(LinkOption... options) - Возвращает реальный путь существующего файла.

    - toString() - Возвращает строковое представление этого пути.

    - toUri() - Возвращает URI, чтобы представить этот путь.

    3. Класс Files?

    Класс Files лежит в пакете java.nio.file. Files является служебным классом, это final-класс с private-конструктором и содержит только статические методы.

    4. Что делает метод read? Почему он возвращает int а не byte? Почему он не может возвращать byte? Что возвращает перегруженный метод с массивом?

    Метод read() возвращает не само значение byte, а его представление в 32х битном виде.

    Метод считывает байты из файла, возвращает int, потому что у него более широкий диапазон чисел. Перегруженный массивом байтов read() возвращает также int.

    5. Каким образом методы read() класса InputStream сигнализируют о достижении конца входного потока?

    Возвращают -1. Это просто означает, что больше нечего читать, позволяя остановить чтение потока до получения IOException.

    6. Что такое путь?

    Путь – это разделенное символами обратной косой черты имя директории или файла. Директория – это тоже самое, что и папка в проводнике Windows.

    7. Абсолютный и относительный путь к файлу?

    - Абсолютный путь — это путь, который указывает на одно и то же место в файловой системе, вне зависимости от текущей директории. Полный путь всегда начинается с корневого каталога.
    - Относительный путь — это путь по отношению к текущему рабочему каталогу.

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

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

    - Относительные пути полезно использовать в случае, когда вы передаёте документы и данные другому пользователю.

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

    - Относительные пути "отсчитываются" от текущей папки, являющейся местоположением сохраненного документа или набора инструментов.

    8. Какая директория используется для превращения относительного пути к файлу в абсолютный путь?

    Текущая директория Java-процесса, т.е. в какой директории введена команда.

    9. Как создать файл на компьютере с помощью Java.

    Для создания нового файла в Java используется класс java.io.File. Во время инициализации объекта File мы должны предоставить ему имя файла, а затем создать сам файл вызовом метода createNewFile(). Этот метод возвращает булево true, если новый файл создан успешно, и false, если файл уже существует. Этот метод также бросает java.io.IOException, когда он не может создать файл.

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

    Класс File наследник Object и implements Serializable, Comparable.

    Экземпляр класса File можно создать как с абсолютным, так и с относительным путём.

    Абсолютный – это когда он однозначно указывает на файл, начиная с корня файловой системы.

    Относительный – это когда чтобы найти файл – нужно знать некую базовую директорию.

    Относительный путь можно превратить в абсолютный при помощи метода .getAbsolutePath(), возвращающего String.

    Или аналогичного метода .getAbsoluteFile(), возвращающего экземпляр File

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

    Для удаления файлов или папок в Java используется метод java.io.File delete(). Он возвращает true, если файл удалился успешно и возвращает false, если указанный для удаления файл не существует или не может быть удален. Если вы пытаетесь удалить папку, то этот метод проверяет указанную папку на пустоту. Если папка пуста, то она удаляется, если в папке что-то есть, то метод delete() просто возвращает false, то есть папка не удаляется.

    КЛОНИРОВАНИЕ И КОПИРОВАНИЕ

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

    ПРОБЛЕМА - Использование оператора присваивания не создает нового объекта, а лишь копирует ссылку на объект. Таким образом, две ссылки указывают на одну и ту же область памяти, на один и тот же объект. Для создания нового объекта с таким же состоянием используется клонирование объекта.

    В Java это возможность создавать объект с аналогичной структурой, как и у исходного объекта. Метод clone() осуществляет побитовое копирование объекта производного класса.

    Чтобы окончательно сделать объект клонируемым, класс должен реализовать интерфейс Cloneable. Интерфейс Cloneable не содержит методов относится к маркерным интерфейсам

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

    Поверхностное копирование копирует настолько малую часть информации об объекте, насколько это возможно. По умолчанию, клонирование в Java является поверхностным, т.е. класс Object не знает о структуре класса, которого он копирует. Клонирование такого типа осуществляется JVM по следующим правилам:

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

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

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

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

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

    3. Какой способ копирования предпочтительней? (конструктор копирования)

    Ещё один вариант клонирования объекта — это конструктор копирования.

    Существует 2 варианта конструктора копирования:

    - Конструктор копирования с поверхностным клонированием;

    - Конструктор копирования с глубоким клонированием.
    Он является наиболее безопасным. Создается конструктор, принимающий на вход объект того же класса, который необходимо клонировать. Его преимущества:

    - Отсутствие ошибок наследования (не нужно беспокоиться, что у наследников появятся новые поля, которые не будут клонированы через метод clone());

    - Поля для клонирования указываются явно;

    - Возможность клонировать даже final поля.

    4. Как сделать глубокое копирование? (3 варианта)

    В Java для клонирования объекта можно использовать:

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

    - Конструктор копирования - в классе описывается конструктор, который принимает объект этого же класса и инициализирует поля создаваемого объекта значениями полей переданного;

    - Механизм сериализации - сохранение и последующее восстановление объекта в/из потока байтов.

    5. Какие копии создаются методом clone() в Java по умолчанию?

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

    СЕРИАЛИЗАЦИЯ И ДЕСЕРИАЛИЗАЦИЯ

    1. Что такое сериализация и десериализация? Как выполняется? Что сериализуется?

    Сериализация — это процесс сохранения состояния объекта в последовательность байт.

    Десериализация — это процесс восстановления объекта из этих байт.

    Для сериализации нужно имплементировать интерфейс Serializable. (у него нет методов). Сделав это мы говорим JVM что всё окей, сейчас будем разбирать объекты на байты (или наоборот байты собирать в объекты). Этот интерфейс является своеобразным флагом.
    Чтобы сериализовать объект, требуется создать выходной поток OutputStream, в который нужно вложить объект ObjectOutputStream. По сути, вызов метода writeObject() осуществляет сериализацию объекта, и далее вы пересылаете его в выходной поток данных OutputStream.
    При десериализации вызывается конструктор без параметров родительского НЕсериализуемого класса (например класса Object). Если такого конструктора не будет – при десериализации возникнет ошибка.

    2. Поле – private static final long serialVersionUID

    При стандартной сериализации важны тип и имя поля. Состав же методов с очень большой вероятностью повлияет на стандартный механизм, при том, что поля могут вообще остаться теми же. Чтобы этого избежать, есть следующий механизм. В каждый класс, реализующий интерфейс Serializable, на стадии компиляции добавляется еще одно поле – private static final long serialVersionUID. Это поле содержит уникальный идентификатор версии сериализованного класса. Оно вычисляется по содержимому класса – полям, их порядку объявления, методам, их порядку объявления. Соответственно, при любом изменении в классе это поле поменяет свое значение.

    При десериализации значение этого поля сравнивается с имеющимся у класса в виртуальной машине. Если значения не совпадают – инициируется исключение InvalidClassException

    2. Какие поля не сериализуются? (поля с ключевым словом transient)

    Если добавить к полю класса ключевое слово transient — значение этого поля не будет сериализовано. Это даёт возможность не упаковывать лишнего.

    При сериализации, полю с ключевым словом transient будет присвоено значение по умолчанию, то есть null.
    При использовании Externalizable никто не мешает сериализовать это поле, равно как и вычитать его. Если поле объявлено transient, то при десериализации объекта оно принимает значение по умолчанию.

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

    При использовании Serializable эти поля вообще не сериализуются (и, соответственно, их значение не меняется, т.к. static поля принадлежат классу, а не объекту). А вот при использовании Externalizable ты управляешь процессом сам, поэтому технически сделать это можно. Но не рекомендуется, так как это чревато трудноуловимыми ошибками.

    4. Сериализация потомков сериализованных родителей.

    При сериализации объекта сериализуются все объекты, на которые он ссылается в своих переменных экземпляра. И если те объекты тоже ссылаются на третьи объекты, они тоже сериализуются. И так до бесконечности. Все классы в этой цепочке должны быть Serializable, иначе их невозможно будет сериализовать и будет выброшено исключение.

    5. Особенность сериализации поля final?

    При использовании Serializable они сериализуются и десериализуются как обычно, а вот при использовании Externalizable десериализовать final-переменную невозможно!

    Причина проста: все final-поля инициализируются при вызове конструктора по умолчанию, и после этого их значение уже невозможно изменить в readExternal. Поэтому для сериализации объектов, содержащих final-поля, используй стандартную сериализацию через Serializable.

    6. Назовите несколько форматов сериализации. (JSON, YAML, XML, BSON)

    JSON

    К объектам, которые сериализуются/десериализуются в JSON есть несколько требований:

    1) поля должны быть видимые: или public или иметь getter’ы и setter’ы;

    2) должен быть конструктор по умолчанию (без параметров).

    Поскольку JSON — объект JavaScript, он поддерживает следующие форматы данных JavaScript:

    - строки (string);

    - числа (number);

    - объекты (object);

    - массивы (array);

    - boolean-значения (true и false);

    - null.
    YAML

    YAML-файл имеет древовидную структуру: одни элементы вложены в другие. Вложенностью мы можем управлять при помощи некоторого количества пробелов, которым обозначаем каждый уровень.
    XML

    XML — распространенный формат, не уступающий JSON и YAML (если говорить об использовании в реальных проектах).
    BSON (binary JSON)

    Бинарный JSON. За счет этого он очень удобен при хранении и передаче изображений и других вложений. Кроме того, BSON поддерживает некоторые типы данных, недоступные в JSON. Например, в BSON-файл можно записать дату (в формате миллисекунд) или даже кусок JavaScript кода.

    Популярная NoSQL база данных MongoDB хранит информацию именно в BSON формате.

    7. Отличия Serializable от Externalizable? (оба являются интерфейсами)

    Serializable удобен и прост в использовании. Практически весь процесс сериализации/десериализации уже написан за программиста, бери и пользуйся, но:

    - У интерфейса Serializable слабая производительность.

    - Отсутствие гибкости. Мы не управляем процессом сериализации-десериализации при использовании интерфейса Serializable. По факту из инструментов у нас есть только transient.

    - Отсутствие безопасности. Если мы работаем с данными вроде паролей, то по-хорошему, эти данные мы должны зашифровать перед записью в файл или передачей по сети. Но Serializable этой возможности не даёт.
    Externalizable

    При имплементации интерфейса Externalizable нужно реализовать два обязательных метода — writeExternal() и readExternal(). Благодаря этим методам у нас решаются проблемы гибкости, производительности и безопасности (все данные зашифровываются). Этот интерфейс во всём лучше.
    _______________________________________________________

    При использовании Serializable под объект просто выделяется память, после чего из потока считываются значения, которыми заполняются все его поля.

    При десериализации вызывается конструктор без параметров родительского НЕсериализуемого класса (например класса Object). Если такого конструктора не будет – при десериализации возникнет ошибка.
    В случае с Externalizable механизм десериализации будет иным. В начале вызывается конструктор класса без параметров. И только потом у созданного объекта UserInfo вызывается метод readExternal(), который и отвечает за заполнение полей объекта.

    Именно поэтому любой класс, имплементирующий интерфейс Externalizable, обязан иметь конструктор без параметров! При использовании наследования, все классы-наследники, происходящие от какого-то Externalizable-класса, тоже должны иметь конструкторы по умолчанию.
    Еще один интересный момент – что будет, если одновременно реализовать у класса Externalizable и Serializable? Как в том вопросе – слон против кита – кто кого поборет?

    Поборет Externalizable. Механизм сериализации сначала проверяет его наличие, а уж потом – наличие Serializable Так что если класс B, реализующий Serializable, наследуется от класса A, реализующего Externalizable, поля класса B сериализованы не будут.
    Подробнее можно посмотреть тут!
    1   2   3


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