_Конспект CORE-1. Core1 1ооп Что такое ооп
Скачать 73.05 Kb.
|
3.Расскажите про обрабатываемые и необрабатываемые исключения В Java все исключения делятся на два типа: - checked (контролируемые/проверяемые исключения) должны обрабатываться блоком catch или описываться в сигнатуре метода (например, throws IOException). Наличие такого обработчика/модификатора сигнатуры проверяются на этапе компиляции; - unchecked (неконтролируемые/непроверяемые исключения), к которым относятся ошибки Error (например, OutOfMemoryError), обрабатывать которые не рекомендуется и исключения времени выполнения, представленные классом RuntimeException и его наследниками (например, NullPointerException), которые могут не обрабатываться блоком catch и не быть описанными в сигнатуре метода. 4.Можно ли обработать необрабатываемые исключения? Согласно спецификации Java, не следует пытаться обрабатывать в собственной программе. Разработчику не предоставлены инструменты для обработки ошибок системы и виртуальной машины. Обрабатывать такие ошибки(Error) не запрещается, но делать этого не рекомендуется. 5. Какой оператор позволяет принудительно выбросить исключение? Это оператор throw: throw new Exception(); 6.О чем говорит ключевое слово throws? Модификатор throws прописывается в сигнатуре метода и указывает на то, что метод потенциально может выбросить исключение с указанным типом. 7.Как создать собственное («пользовательское») исключение? Необходимо унаследоваться от базового класса требуемого типа исключений (например от Exception или RuntimeException). 8.Расскажите про механизм обработки исключений в java (Try-catch-finally) try — данное ключевое слово используется для отметки начала блока кода, который потенциально может привести к ошибке. catch — ключевое слово для отметки начала блока кода, предназначенного для перехвата и обработки исключений в случае их возникновения. finally — ключевое слово для отметки начала блока кода, который является дополнительным. Этот блок помещается после последнего блока catch. Управление передаётся в блок finally в любом случае, было выброшено исключение или нет. Общий вид конструкции для обработки исключительной ситуации выглядит следующим образом: try { //код, который потенциально может привести к исключительной ситуации } catch(SomeException e ) { //в скобках указывается класс конкретной ожидаемой ошибки //код обработки исключительной ситуации } finally { //необязательный блок, код которого выполняется в любом случае } 9.Возможно ли использование блока try-finally (без catch)? Такая запись допустима, но смысла в такой записи не так много, всё же лучше иметь блок catch, в котором будет обрабатываться необходимое исключение. 10.Может ли один блок catch отлавливать сразу несколько исключений? В Java 7 стала доступна новая языковая конструкция, с помощью которой можно перехватывать несколько исключений одним блоком catch: try { //... } catch(IOException | SQLException ex) { //... } 11.Всегда ли выполняется блок finally? Существуют ли ситуации, когда блок finally не будет выполнен? Код в блоке finally будет выполнен всегда, независимо от того, выброшено исключение или нет. Когда JVM «умирает» - в такой ситуации finally недостижим и не будет выполнен, так как происходит принудительный системный выход из программы. 12.Может ли метод main() выбросить исключение во вне и если да, то где будет происходить обработка данного исключения? Может и оно будет передано в виртуальную машину Java (JVM). 13.В каком порядке следует обрабатывать исключения в catch блоках? Если в блоке try возникает исключение, управление выполнением передается соответствующему блоку catch. С одним try может быть связано несколько catch, которые необходимо размещать таким образом, чтобы общий catch обработчика исключений был последним. Универсальный обработчик исключений может обрабатывать все исключения, но вы должны поместить его в конец, если вы поместите его перед перед всеми блоками перехвата, он отобразит общее сообщение. 14.Что такое механизм try-with-resources? try-with-resources , также называемый автоматическим управлением ресурсами , — это новый механизм обработки исключений, представленный в Java 7, который автоматически закрывает ресурсы, используемые в блоке try catch. Чтобы использовать этот оператор, вам просто нужно объявить необходимые ресурсы в круглых скобках, и созданный ресурс будет автоматически закрыт в конце блока. 15.Что произойдет если исключение будет выброшено из блока catch после чего другое исключение будет выброшено из блока finally? Если не одна функция в стэке вызовов не способна обработать исключение, ошибка выводиться пользователю и программа завершается досрочно. 16.Что произойдет если исключение будет выброшено из блока catch после чего другое исключение будет выброшено из метода close() при использовании try-with-resources? Программа завершится досрочно, произойдет утечка ресурса (не закроется соединение, не будет освобожден файловый дескриптор и т.д.) [6*Сериализация и копирование] 1.Что такое сериализация и как она реализована в Java? Сериализация (Serialization) - процесс преобразования структуры данных в линейную последо- вательность байтов для дальнейшей передачи или сохранения. Сериализованные объекты можно затем восстановить (десериализовать). В Java, согласно спецификации Java Object Serialization существует два стандартных способа сериа- лизации: стандартная сериализация, через использование интерфейса java.io.Serializable и «расширенная» сериализация - java.io.Externalizable. 2.Для чего нужна сериализация? Сериализация позволяет в определенных пределах изменять класс. Вот наиболее важные измене- ния, с которыми спецификация Java Object Serialization может справляться автоматически: - добавление в класс новых полей; - изменение полей из статических в нестатические; - изменение полей из транзитных в нетранзитные. Обратные изменения (из нестатических полей в статические и из нетранзитных в транзитные) или удаление полей требуют определенной дополнительной обработки в зависимости от того, какая степень обратной совместимости необходима. 3.Опишите процесс сериализации/десериализации с использованием Serializable. При использовании Serializable применяется алгоритм сериализации, который с помощью рефлек- сии (Reflection API) выполняет: - запись в поток метаданных о классе, ассоциированном с объектом (имя класса, идентификатор SerialVersionUID, идентификаторы полей класса); - рекурсивную запись в поток описания суперклассов до класса java.lang.Object (не включительно); запись примитивных значений полей сериализуемого экземпляра, начиная с полей самого верх- него суперкласса; - рекурсивную запись объектов, которые являются полями сериализуемого объекта. При этом ранее сериализованные объекты повторно не сериализуются, что позволяет алгоритму корректно работать с циклическими ссылками. Для выполнения десериализации под объект выделяется память, после чего его поля заполняются значениями из потока. Конструктор объекта при этом не вызывается. Однако при десериализации будет вызван конструктор без параметров родительского несериализуемого класса, а его отсутствие повлечёт ошибку десериализации. 4.Как изменить стандартное поведение сериализации/десериализации? Реализовать интерфейс java.io.Externalizable, который позволяет применение пользователь- ской логики сериализации. Способ сериализации и десериализации описывается в методах writeExternal() и readExternal(). Во время десериализации вызывается конструктор без параметров, а потом уже на созданном объекте вызывается метод readExternal. Если у сериализуемого объекта реализован один из следующих методов, то механизм сериализа- ции будет использовать его, а не метод по умолчанию: writeObject() - запись объекта в поток; readObject() - чтение объекта из потока; writeReplace() - позволяет заменить себя экземпляром другого класса перед записью; readResolve() - позволяет заменить на себя другой объект после чтения. 5.Какие поля не будут сериализованы при сериализации? Будет ли сериализовано final поле? Поля класса, помеченные модификатором transient, не сериализуются. Обычно в таких полях хранится промежуточное состояние объекта, которое, к примеру, проще вычислить. Другой пример такого поля - ссылка на экземпляр объекта, который не требует сериа- лизации или не может быть сериализован. При стандартной сериализации поля, имеющие модификатор static, не сериализуются. Соответ- ственно, после десериализации это поле значения не меняет. При использовании реализации Externalizable сериализовать и десериализовать статическое поле можно, но не рекомендуется этогоделать, т.к. это может сопровождаться трудноуловимыми ошибками. Поля с модификатором final сериализуются как и обычные. За одним исключением – их невозможно десериализовать при использовании Externalizable, поскольку final поля должны быть инициализированы в конструкторе, а после этого в readExternal() изменить значение этого поля будет невозможно. Соответственно, если необходимо сериализовать объект с final полем необходимо использовать только стандартную сериализацию. 6.Как создать собственный протокол сериализации? Для создания собственного протокола сериализации достаточно реализовать интерфейс Externalizable, который содержит два метода: public void writeExternal(ObjectOutput out) throws IOException; public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException; 7.Какая роль поля serialVersionUID в сериализации? serialVersionUID используется для указания версии сериализованных данных. Когда мы не объявляем serialVersionUID в нашем классе явно, среда выполнения Java делает это за нас, но этот процесс чувствителен ко многим метаданным класса включая количество полей, тип полей, модификаторы доступа полей, интерфейсов, которые реализованы в классе и пр. Рекомендуется явно объявлять serialVersionUID т.к. при добавлении, удалении атрибутов класса динамически сгенерированное значение может измениться и в момент выполнения будет выброшено исключение InvalidClassException. 8.Когда стоит изменять значение поля serialVersionUID? serialVersionUID нужно изменять при внесении в класс несовместимых изменений, например при удалении какого-либо его атрибута. 9.В чем проблема сериализации Singleton? Проблема в том что после десериализации мы получим другой объект. Таким образом, сериализация дает возможность создать Singleton еще раз, что недопустимо. Существует два способа избежать этого: - явный запрет сериализации. - определение метода с сигнатурой (default/public/private/protected/) Object readResolve() throws ObjectStreamException, назначением которого станет возврат замещающего объекта вместо объекта, на котором он вызван. 10.Расскажите про клонирование объектов. Использование оператора присваивания не создает нового объекта, а лишь копирует ссылку на объект. Таким образом, две ссылки указывают на одну и ту же область памяти, на один и тот же объект. Для создания нового объекта с таким же состоянием используется клонирование объекта. Класс Object содержит protected метод clone(), осуществляющий побитовое копирование объекта производного класса. Однако сначала необходимо переопределить метод clone() как public для обеспечения возможности его вызова. В переопределенном методе следует вызвать базовую версию метода super.clone(), которая и выполняет собственно клонирование. Чтобы окончательно сделать объект клонируемым, класс должен реализовать интерфейс Cloneable. Интерфейс Cloneable не содержит методов относится к маркерным интерфейсам, а его реализация гарантирует, что метод clone() класса Object возвратит точную копию вызвавшего его объекта с воспроизведением значений всех его полей. В противном случае метод генерирует исключение CloneNotSupportedException. Следует отметить, что при использовании этого механизма объект создается без вызова конструктора. Помимо встроенного механизма клонирования в Java для клонирования объекта можно использовать: - Специализированный конструктор копирования - в классе описывается конструктор, который принимает объект этого же класса и инициализирует поля создаваемого объекта значениями полей переданного. - Фабричный метод - (Factory method), который представляет собой статический метод, возвращающий экземпляр своего класса. - Механизм сериализации - сохранение и последующее восстановление объекта в/из потока байтов. 11.В чем отличие между поверхностным и глубоким клонированием? Поверхностное копирование копирует настолько малую часть информации об объекте, насколько это возможно. По умолчанию, клонирование в Java является поверхностным, т.е. класс Object не знает о структуре класса, которого он копирует. Клонирование такого типа осуществляется JVM по следующим правилам: Если класс имеет только члены примитивных типов, то будет создана совершенно новая копия объекта и возвращена ссылка на этот объект. Если класс помимо членов примитивных типов содержит члены ссылочных типов, то тогда копируются ссылки на объекты этих классов. Следовательно, оба объекта будут иметь одинаковые ссылки. Глубокое копирование дублирует абсолютно всю информацию объекта: Нет необходимости копировать отдельно примитивные данные; Все члены ссылочного типа в оригинальном классе должны поддерживать клонирование. Для каждого такого члена при переопределении метода clone() должен вызываться super.clone(); Если какой-либо член класса не поддерживает клонирование, то в методе клонирования необходимо создать новый экземпляр этого класса и скопировать каждый его член со всеми атрибутами в новый объект класса, по одному. 12.Какой способ клонирования предпочтительней? Наиболее безопасным и, следовательно, предпочтительным способом клонирования является использование специализированного конструктора копирования: Отсутствие ошибок наследования (не нужно беспокоиться, что у наследников появятся новые поля, которые не будут склонированы через метод clone()); Поля для клонирования указываются явно; Возможность клонировать даже final поля. 13.Почему метод clone() объявлен в классе Object, а не в интерфейсе Cloneable? Метод clone() объявлен в классе Object с указанием модификатора native, чтобы обеспечить доступ к стандартному механизму поверхностного копирования объектов. Одновременно он объявлен и как protected, чтобы нельзя было вызвать этот метод у не переопределивших его объектов. Непосредственно интерфейс Cloneable является маркерным (не содержит объявлений методов) и нужен только для обозначения самого факта, что данный объект готов к тому, чтобы быть клонированным. Вызов переопределённого метода clone() у не Cloneable объекта вызовет выбрасывание CloneNotSupportedException. 14.Как создать глубокую копию объекта? (2 способа) Первое - Копировать конструктор. Вторая реализация основана на методе клонирования, унаследованном от Object. Он защищен, но нам нужно переопределить его как public. Для получения глубокой копии мы можем сериализовать объект и затем десериализовать его в новый объект. |