JavaCore4: OOP Flashcards
Какие виды классов есть в java?
- Top level class (обычный класс):
◦ Concrete class (обычный класс);
◦ Abstract class (абстрактный класс);
◦ Final class (финализированный класс). - Interfaces (интерфейс) - содержит набор абстрактных методов, подлежащих реализации в имплементирующих его обычных классах
- Enum (перечисление) - специальный тип К., представляющий ограниченный проименованный набор значений.
- Nested class (вложенный класс):
◦ Static nested class (статический вложенный класс): ассоциирован с внешним К., но не с его объектом;
◦ Member inner class (простой внутренний класс): ассоциирован с объектом внешнего класса;
◦ Local inner class (локальный класс): создается внутри метода и не доступен за его пределами.;
◦ Anonymous inner class (анонимный класс): безымянный класс, созданный и инстанциированный в одном выражении. - Lambda expression - сущность функционального интерфейса или анонимная функция, обладающая свойствами объекта.
В каких случаях применяются вложенные классы? (2)
1) Он должен создаваться только для того, чтобы обслуживать обрамляющий
его класс.
2) Если вложенный класс оказывается полезен в каком-либо ином контексте, он
должен стать классом верхнего уровня.
Основные различия статических и внутренних классов?
1) В. имеет доступ ко всем членам внешнего к., С. только к static
2) В. привязан (и может быть инициализирован) к объекту внешнего класса, С. независим от него и может быть вызван напрямую, или с объектом: Outer.StaticInner.staticMethod(); / outerObj = Outer.StaticInner(); outerObj.staticMethod();
Т.о., если для использования внутреннего к. мы можем обойтись без объекта внешнего к. - класс д.б. static.
4) 3) В. не может иметь static полей и методов, С. может иметь и те и те, доступ к ним возможен через объект этого статического класса.
Основные свойства локальных классов? (5)
Используется если класс необходим только внутри какого-то метода и требуется
создавать экземпляры этого класса только в этом методе.
1) видны только в пределах блока, в котором объявлены;
2) не могут быть объявлены как private/public/protected или static (по этой причине
интерфейсы нельзя объявить локально);
3) не могут иметь внутри себя статических объявлений (полей, методов, классов), но
могут иметь константы (static final);
4) имеют доступ к полям и методам обрамляющего класса;
5) могут обращаться к локальным переменным и параметрам метода, если они
объявлены с модификатором final или являются effectively final.
Основные свойства анонимных классов? (5)
- объявляется, инициализируется и используется в одном месте программы – месте его создания;
- реализует лишь методы своего интерфейса или суперкласса, т. е. не может объявлять каких-либо новых методов, так как для доступа к ним нет
поименованного типа. - применяется для создания объекта функции (function object), например, реализация интерфейса
Comparator; - применяется для создания объекта процесса (process object), такого как экземпляры классов
Thread, Runnable и подобных;
Что такое перечисления (enum)?
- Это набор логически связанных констант.
- Все элементы под капотом инициализируются как public static final
- Нужны для ограничения области допустимых значений: например, времена года, дни недели.
Какие методы есть у Enum?
- valueOf() возвращает конкретный элемент;
- ordinal() возвращает порядковый номер определенной константы (нумерация начинается с 0);
- values() возвращает массив всех констант перечисления;
- name() отличается от toString тем, что второй можно переопределить.
Особенности Enum-классов (5)
1) Конструктор всегда private или default. Нет public конструктора, поэтому нельзя создать экземпляр вне Enum => Легко создать потокобезопасный singleton без double check volatile переменных.
2) Могут имплементировать интерфейсы.
3) Не могут наследовать класс.
4) При equals() выполняется ==.
5) Может использоваться в TreeSet и TreeMap, т. к. имплементирует
Comparable => compareTo() имитирует порядок элементов, предоставляемый ordinal().
Дайте определение понятию «конструктор»
- Конструктор – это специальный метод, у которого отсутствует возвращаемый тип и который
имеет то же имя, что и класс, в котором он используется. - Конструктор вызывается при
создании нового объекта класса и определяет действия, необходимые для его
инициализации.
Что такое конструктор по умолчанию? (3)
- Если у какого-либо класса не определить конструктор, то компилятор сгенерирует
конструктор без аргументов – так называемый «конструктор по умолчанию». - Если у класса уже определен какой-либо конструктор, то конструктор по умолчанию создан
не будет и, если он необходим, его нужно описывать явно. - В классе-наследнике при отсутствии переопределенного конструктора будет использован
конструктор родителя.
Для чего нужны приватные конструкторы?
Приватный конструктор запрещает создание экземпляра класса вне методов самого класса.
Нужны для реализации паттернов, например, singleton, static factory(запрещает создание через конструктор - используем метод)
Чем отличаются конструкторы по умолчанию, конструктор копирования и
конструктор с параметрами?
- у конструктора по умолчанию отсутствуют какие-либо аргументы;
- конструктор копирования принимает в качестве аргумента уже существующий
объект класса для последующего создания его клона; - конструктор с параметрами имеет в своей сигнатуре аргументы (обычно
необходимые для инициализации полей класса).
Какие модификаторы доступа есть в Java? Какие применимы к классам?
private (приватный): члены класса доступны только внутри класса. Для обозначения
используется служебное слово private.
default, package-private, package level (доступ на уровне пакета): видимость класса/членов
класса только внутри пакета. Является модификатором доступа по умолчанию –
специальное обозначение не требуется.
protected (защищенный): члены класса доступны внутри пакета и в наследниках. Для
обозначения используется служебное слово protected.
public (публичный): класс/члены класса доступны всем. Для обозначения используется
служебное слово public.
Последовательность модификаторов по возрастанию уровня закрытости: public, protected,
default, private.
Во время наследования возможно изменения модификаторов доступа в сторону большей
видимости (для поддержания соответствия принципу подстановки Барбары Лисков).
Класс может быть объявлен с модификатором public и default.
Может ли объект получить доступ к члену класса объявленному как private?
Если да, то каким образом? (4)
- внутри класса доступ к приватной переменной открыт без ограничений;
- вложенный класс имеет полный доступ ко всем (в том числе и приватным) членам
содержащего его класса; - доступ к приватным переменным извне может быть организован через отличные
от приватных методы, которые предоставлены разработчиком класса. Например:
getX() и setX(). - через механизм рефлексии (Reflection API).
Что означает модификатор static?
Статическая переменная – это переменная, принадлежащая классу, а не объекту.
Статический класс – это вложенный класс, который может обращаться только к
статическим полям обертывающего его класса.
Внутри статического метода нельзя вызвать нестатический
К каким конструкциям Java применим модификатор static? (5)
- полям;
- методам;
- вложенным классам;
- членам секции import;
- блокам инициализации.
Может ли статический метод быть переопределен или перегружен?
Перегружен – да. Переопределен - нет.
Могут ли нестатические методы перегрузить статические?
Да. В итоге получится два разных метода. Статический будет принадлежать классу и будет
доступен через его имя, а нестатический будет принадлежать конкретному объекту и
доступен через вызов метода этого объекта.
Как получить доступ к переопределенным методам родительского класса?
С помощью ключевого слова super мы можем обратиться к любому члену родительского
класса – методу или полю, если они не определены с модификатором private.
super.method();
Можно ли сузить уровень доступа/тип возвращаемого значения при
переопределении метода?
При переопределении метода нельзя сузить модификатор доступа к методу (например, с
public до private), но можно расширить.
Изменить тип возвращаемого значения нельзя, но можно сузить возвращаемое
значение, если они совместимы. Например, если метод возвращает объект класса, а
переопределенный метод возвращает класс-наследник:
Ковариантность возвращаемого значения
Можно ли
менять при переопределении менять throws?
Секцию throws метода можно не указывать, но стоит помнить, что она остается
действительной, если уже определена у метода родительского класса. Можно
добавлять новые исключения, являющиеся наследниками от уже объявленных или
исключения RuntimeException. Порядок следования таких элементов при переопределении
значения не имеет.
Что означает модификатор final для разных сущностей? (7)
- класс не может иметь наследников;
- метод не может быть переопределен в классах-наследниках;
- поле не может изменить свое значение после инициализации;
- параметры методов не могут изменять свое значение внутри метода;
- для локальных переменных примитивного типа это означает, что однажды
присвоенное значение не может быть изменено; - для ссылочных переменных это означает, что после присвоения объекта нельзя
изменить ссылку на данный объект (ссылку изменить нельзя, но состояние
объекта изменять можно).
Следует также отметить, что к abstract-классам нельзя применить модификатор final, т.
к. это взаимоисключающие понятия.
Где и для чего используется модификатор abstract?
1) классы могут выступать только предками для других классов.
2) Метод, помеченный ключевым словом abstract, – абстрактный метод, т. е. метод, который не
имеет реализации. Если в классе присутствует хотя бы один абстрактный метод, то весь
класс должен быть объявлен абстрактным
3) Использование абстрактных классов и методов позволяет описать некий шаблон объекта,
который должен быть реализован в других классах. В них же самих описывается лишь некое
общее для всех потомков поведение.
4) абстрактный метод не может быть вне абстрактного класса;
Что такое интерфейсы?
- Интерфейс – это совокупность полей и методов, определяющих правила взаимодействия
элементов системы. - Основное предназначение интерфейса – определять, каким образом можно использовать
класс, который его реализует.
Какие модификаторы по умолчанию имеют поля и
методы интерфейсов?
Методы: public abstract
Поля: public static final
Чем интерфейсы отличаются от абстрактных классов? (5)
- Интерфейс описывает только поведение (методы) объекта, а вот полей у
него нет (кроме констант), в то время как у абстрактного класса они могут быть. - Можно наследовать только один класс, а реализовать интерфейсов сколько угодно.
Интерфейс может наследовать (extends) другой интерфейс/интерфейсы. - Абстрактные классы используются, когда есть отношение «is-a», то есть класс-
наследник расширяет базовый абстрактный класс, а интерфейсы могут быть
реализованы разными классами, вовсе не связанными друг с другом. - Абстрактный класс может реализовывать методы; интерфейс может реализовывать
статические методы начиная с 8-й версии. - Нет конструктора у интерфейса.
Что такое static метод интерфейса? Для чего используются?
- Статические методы интерфейса похожи на методы по умолчанию, за исключением того, что для них отсутствует возможность переопределения в классах, реализующих интерфейс.
- Статические методы в интерфейсе используются для обеспечения вспомогательных методов, например, проверки на null, сортировки коллекций и т.д.
instanceof VS getClass
instanceof
Оператор instanceof сравнивает объект и указанный тип. Его можно использовать для проверки является ли данный объект экземпляром некоторого класса, либо экземпляром его дочернего класса, либо экземпляром класса, который реализует указанный интерфейс.
this.getClass() == that.getClass() проверяет два класса на идентичность, поэтому для корректной реализации контракта метода equals() необходимо использовать точное сравнение с помощью метода getClass().
Что такое маркерный интерфейс?
И. без методов: служит для маркировки класса на соответствие определенному типу (serializable)
Что такое Блоки инициализации?
Код, заключенный в фигурные скобки и размещаемый внутри класса вне объявления методов или конструкторов.
Существуют статические и нестатические блоки инициализации.
Генерят ли блоки инициализации исключения?
Блок инициализации способен генерировать исключения, если их объявления перечислены в throws всех конструкторов класса.
Если возникшее исключение - наследник RuntimeException:
для статических блоков инициализации будет выброшено java.lang.ExceptionInInitializerError;
для нестатических будет проброшено исключение-источник.
Если возникшее исключение - наследник Error, то в обоих случаях будет выброшено java.lang.Error. Исключение: java.lang.ThreadDeath - смерть потока. В этом случае никакое исключение выброшено не будет.
Для чего в Java используются статические блоки инициализации?
Статические блоки инициализация используются для выполнения кода, который должен выполняться один раз при инициализации класса загрузчиком классов, в момент предшествующий созданию объектов этого класса при помощи конструктора.
Порядок вызова конструкторов и блоков инициализации с учётом иерархии классов.
Parent static block → Child static block → Grandchild static block
→ Parent non-static block →
Parent constructor →
→ Child non-static block→ Child constructor →
→ Grandchild non-static block → Grandchild constructor
Что такое класс Object?
Базовый класс для всех остальных объектов в Java. Любой класс наследуется от Object и, соответственно, наследуют его методы
Все классы являются наследниками суперкласса Object. Это не нужно указывать явно. В результате объект Object может ссылаться на объект любого другого класса.
Какие методы есть у класса Object (перечислить все)? Что они делают?
- equals() - проверка на равенство двух обьектов
- hashCode() - изначально случайно число int
- toString() - представления данного объекта в виде строки.
- getClass() - получение типа данного обьекта
- clone() - клонирует объект методом.
- finalize() - deprecated, вызывается GC перед удалением. (нет гарантии что будет вызван)
для многопоточки:
- notify() - «размораживает» одну случайную нить
- notifyAll() - «размораживает» все нити данного монитора
- wait() - нить освобождает монитор и «становится на паузу»
Что такое hash-code?
- Хеш-код — это целочисленный результат работы метода, которому в качестве входного параметра передан объект.
- Он реализован таким образом, что для одного и того же входного объекта, хеш-код всегда будет одинаковым.
Для чего нужен метод hashCode()?
вычисляет целочисленное значение для конкретного элемента класса, чтобы использовать его для быстрого поиска и доступа к этому элементу в hash-структурах данных, например, HashMap, HashSet и прочих.
Пересчитывается ли hash-code для объекта автоматически при изменении его состояния?
Нет. JVM пересчитывает hashcode объекта только когда это требуется:
- когда О. становится ключом для хэш-структуры, поэтому map.contains(key) вернет false, если состояние объекта изменилось после добавления в мапу.
Есть ли какие-либо рекомендации о том, какие поля следует использовать при подсчете hashCode()?
Выбирать поля, которые с большой долью вероятности будут различаться:
Для этого необходимо использовать уникальные, лучше всего примитивные поля, например такие как id, uuid.
При этом нужно следовать правилу, если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().
Что такое метод equals()?
Equals - это метод, определенный в Object, который служит для сравнения объектов.
equals в Object сравнивает по “==”
Свойства equals()? (6)
- Симметричность: если a.equals(b) то b.equals(a)
- Рефлексивность: x.equals(x)
должно возвращать true. - Постоянство: повторный вызов метода equals() должен возвращать одно и тоже значение до тех пор, пока какое-либо значение свойств объекта не будет изменено.
- Транзитивность: Если a.equals(b) и b.equals(c), то тогда a.equals(c)
- Совместимость с hashCode(): Два тождественно равных объекта должны иметь одно и то же значение hashCode()
- a.equals(null) -> false
Какой контракт между hashCode() и equals()?
1) Если два объекта возвращают разные значения hashcode(), то они не могут быть равны
2) Если equals объектов true, то и хэшкоды должны быть равны, при этом наоборот не всегда (коллизия).
3) Переопределив equals, всегда переопределять и hashcode.
Что будет, если переопределить equals() не переопределяя hashCode()?
Нарушится контракт -> hash-code будет вычисляться как у предка, и равные по equals() будут помещены в разные ячейки hashmap.
Какие поля использовать при переопределении hashcode?
- Те же, что и в equals()
- Желательно уникальные для объекта поля, не подверженные изменению.