ООП. JAVA Flashcards

1
Q

Какие виды классов есть в java?

A
  • Top level class (Обычный класс):
    • Abstract class (Абстрактный класс);
    • Final class (Финализированный класс).
  • Interfaces (Интерфейс).
  • Enum (Перечисление).
  • Nested class (Вложенный класс):
    • Static nested class (Статический вложенный класс);
    • Member inner class (Простой внутренний класс);
    • Local inner class (Локальный класс);
    • Anonymous inner class (Анонимный класс).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Расскажите про вложенные классы. В каких случаях они применяются?

A

Класс называется вложенным (Nested class), если он определен внутри другого класса. Вложенный класс должен создаваться только для того, чтобы обслуживать обрамляющий его класс.
Если вложенный класс оказывается полезен в каком-либо ином контексте, он должен стать классом верхнего уровня.
Вложенные классы имеют доступ ко всем (в том числе приватным) полям и методам внешнего класса, но не наоборот.

  1. Статические вложенные классы (Static nested classes)
    – Есть возможность обращения к внутренним статическим полям и методам класса обертки.
  2. Вложенные классы
    – Есть возможность обращения к внутренним полям и методам класса обертки.
    – Не может иметь статических объявлений.
    – Внутри такого класса нельзя объявить перечисления.
    – Если нужно явно получить this внешнего класса — OuterClass.this
  3. Локальный класс
    – Видны только в пределах блока, в котором объявлены.
    – Не могут быть объявлены как private/public/protected или static (по этой причине интерфейсы нельзя объявить локально).
    – Не могут иметь внутри себя статических объявлений (полей, методов, классов), но могут иметь константы (static final)
    – Имеют доступ к полям и методам обрамляющего класса.
    – Можно обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором final или являются effectively final.
  4. Анонимные классы
    – Локальный класс без имени.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Что такое «локальный класс»? Каковы его особенности?

A

Local inner class (Локальный класс) - это вложенный класс, созданный внутри тела метода. Только этот метод имеет к ним доступ.
~~~
public class OuterClass {
public void someMethod(){
class LocalClass{
}
}
}
~~~
Локальные классы имеют следующие особенности:
* Видны только в пределах блока, в котором объявлены;
* Не могут быть объявлены как private/public/protected или static;
* Не могут иметь внутри себя статических объявлений (полей, методов, классов);
* Имеют доступ к полям и методам обрамляющего класса;
* Могут обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором final.
* Может наследовать: обычные классы; внутренние классы в OuterClassе и его предках; такие же локальные классы определённые в том же методе.
* Может быть наследован таким же локальным классом определённом в том же методе.
* Может имплементировать интерфейс

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Что такое «анонимные классы»? Где они применяются?

A

Анонимный класс - Это вложенный локальный класс без имени. Класс, определяемый как подкласс некоторого данного класса прямо в процессе задания переменной.

public class OuterClass {
    public void someMethod(){
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                return null;
            }
        };
    }
}

Анонимные классы имеют несколько ограничений:

  • Их использование разрешено только в одном месте программы - месте его создания;
  • Применение возможно только в том случае, если после порождения экземпляра нет необходимости на него ссылаться;
  • Реализует лишь методы своего интерфейса или суперкласса, т.е. не может объявлять каких-либо новых методов, так как для доступа к ним нет поименованного типа.
  • Не может быть наследован
    Анонимные классы обычно применяются для:
    а) Создания объекта функции (function object), например реализация интерфейса Comparator;
    создания объекта процесса (process object), такого как экземпляры классов Thread, Runnable и подобных;
    b) В статическом методе генерации;
    с) Инициализации открытого статического поля final, которое соответствует сложному перечислению типов, когда для каждого экземпляра в перечислении требуется отдельный подкласс.
    Анонимные классы всегда являются конечными классами.
    Каждое объявление анонимного класса уникально. Видны только внутри того метода, в котором определены.
    В документации Oracle приведена хорошая рекомендация: «Применяйте анонимные классы, если вам нужен локальный класс для одноразового использования».
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Каким образом из вложенного класса получить доступ к полю внешнего класса?

A

1) Статический вложенный класс имеет прямой доступ только к статическим полям обрамляющего класса.
2) Простой вложенный класс, может обратиться к любому полю внешнего класса напрямую.
3) В случае, если у вложенного класса уже существует поле с таким же литералом, то обращаться к внешнему полю следует через имя внешнего класса. Например: Outer.this.field.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Что такое перечисления (enum)?

A
  • Перечисления представляют набор логически связанных констант.
  • Перечисление фактически представляет новый класс, поэтому можно определить переменную данного типа и использовать ее.
  • Перечисления, как и обычные классы, могут определять конструкторы, поля и методы.
  • При этом конструктор по умолчанию приватный. Также можно определять методы для отдельных констант.
  • Можно создавать публичные геттеры\сеттеры. Они создаются в момент компиляции.

Методы:
* valueOf() возвращает конкретный элемент;
* ordinal() возвращает порядковый номер определенной константы (нумерация
начинается с 0);
* values() возвращает массив всех констант перечисления;
* name() отличается от toString тем, что второй можно переопределить.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Особенности Enum-классов

A
  • Конструктор всегда private или default.
  • Могут имплементировать интерфейсы.
  • Не могут наследовать класс.
  • Можно переопределить toString().
  • Нет public конструктора, поэтому нельзя создать экземпляр вне Enum.
  • При equals() выполняется ==.
  • ordinal() возвращает порядок элементов.
  • Может использоваться в TreeSet и TreeMap, т. к. Enum имплементирует Comparable.
  • compareTo() имитирует порядок элементов, предоставляемый ordinal().
  • Можно использовать в Switch Case.
  • values() возвращает массив всех констант.
  • Легко создать потокобезопасный singleton без double check volatile переменных.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Недостатки Enum-классов

A
    • К ним не применимы операторы >, <, >=, <=
    • enum также требует больше памяти для хранения чем обычная константа.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Что такое Ромбовидное наследование?

A

Ромбовидное наследование (англ. diamond inheritance) – ситуация в объектно- ориентированных языках программирования с поддержкой множественного наследования, когда два класса B и C наследуют от A, а класс D наследует от обоих классов B и C.
При этой схеме наследования может возникнуть неоднозначность: если объект класса D вызывает метод, определенный в классе A (и этот метод не был переопределен в классе D), а классы B и C по-своему переопределили этот метод, то от какого класса его наследовать:
B или C?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Как проблема ромбовидного наследования решена в java?

A

В Java нет поддержки множественного наследования классов.

Предположим, что SuperClass – это абстрактный класс, описывающий некоторый метод, а
классы ClassA и ClassB – обычные классы наследники SuperClass, а класс ClassC
наследуется от ClassA и ClassB одновременно. Вызов метода родительского класса
приведет к неопределенности, так как компилятор не знает о том, метод какого именно
суперкласса должен быть вызван. Это и есть основная причина, почему в Java нет
поддержки множественного наследования классов. Интерфейсы – это только
резервирование/описание метода, а реализация самого метода будет в конкретном классе, реализующем эти интерфейсы, таким образом исключается неопределенность при множественном наследовании интерфейсов. В случае, если вызывается default-метод из интерфейса его обязательно надо будет переопределить.

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Что такое конструктор по умолчанию?

A

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

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Могут ли быть приватные конструкторы? Для чего они нужны?

A

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

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

Нужен для реализации паттернов, например singleton.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Расскажите про классы-загрузчики и про динамическую загрузку классов.

A

При запуске JVM, используются три загрузчика классов:

  • Bootstrap ClassLoader - главный загрузчик - загружает платформенные классы JDK из архива rt.jar
  • AppClassLoader - системный загрузчик - загружает классы приложения, определенные в CLASSPATH
  • Extension ClassLoader - загрузчик расширений - загружает классы расширений, которые по умолчанию находятся в каталоге jre/lib/ext.

Динамическая загрузка происходит “на лету” в ходе выполнения программы с помощью статического метода класса Class.forName(имя класса).
Для чего нужна динамическая загрузка?
Например мы не знаем какой класс нам понадобится и принимаем решение в ходе выполнения программы передавая имя класса в статический метод forName().

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Чем отличаются конструкторы по-умолчанию, конструктор копирования и конструктор с параметрами?

A

-У конструктора по умолчанию отсутствуют какие-либо аргументы.

-Конструктор копирования принимает в качестве аргумента уже существующий объект класса для последующего создания его клона.

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Какие модификаторы доступа есть в Java? Какие применимы к классам?

A

private (приватный): члены класса доступны только внутри класса. Для обозначения
используется служебное слово private.
default, package-private, package level (доступ на уровне пакета): видимость класса/членов класса только внутри пакета. Является модификатором доступа по умолчанию – специальное обозначение не требуется.
protected (защищенный): члены класса доступны внутри пакета и в наследниках. Для
обозначения используется служебное слово protected.
public (публичный): класс/члены класса доступны всем. Для обозначения используется служебное слово public.
Последовательность модификаторов по возрастанию уровня закрытости: public-> protected->default->private.
Во время наследования возможно изменения модификаторов доступа в сторону большей видимости (для поддержания соответствия принципу подстановки Барбары Лисков).
Класс может быть объявлен с модификатором public и default.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Может ли объект получить доступ к члену класса объявленному как private?
Если да, то каким образом?

A
  • внутри класса доступ к приватной переменной открыт без ограничений;
  • вложенный класс имеет полный доступ ко всем (в том числе и приватным) членам содержащего его класса;
  • доступ к приватным переменным извне может быть организован через отличные
    от приватных методы, которые предоставлены разработчиком класса. Например:
    getX() и setX().
  • через механизм рефлексии (Reflection API).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Что означает модификатор static?

A

Статическая переменная - это переменная, принадлежащая классу, а не объекту.

А статический класс- это вложенный класс, который может обращаться только к статическим полям обертывающего его класса.

Внутри static метода нельзя вызвать не статический метод по имени класса.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

К каким конструкциям Java применим модификатор static?

A
  • полям;
  • методам;
  • вложенным классам;
  • членам секции import;
  • блокам инициализации.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Может ли статический метод быть переопределён или перегружен?

A

Нельзя переопределять статические методы.
Если вы объявите такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса вместо переопределения. Это явление известно как сокрытие методов (hiding methods).

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

Перегружен - да. Всё работает точно так же как и с обычными методами - 2 статических метода могут иметь одинаковое имя, если количество их параметров или типов различается.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Могут ли нестатические методы перегрузить статические?

A

Да. Это будут просто два разных метода для программы. Статический будет доступен по имени класса.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

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

A

При переопределении метода нельзя сузить модификатор доступа к методу (например, с public до private), но можно расширить.

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

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Что можно изменить в сигнатуре метода при переопределении?
Можно ли менять модификаторы (throws и тп)?

A

В сигнатуре(имя + параметры) менять ничего нельзя.

Возможно расширение уровня доступа.

Изменять тип возвращаемого значения при переопределении метода разрешено только в сторону сужения типа (вместо родительского класса - наследника).

Секцию throws метода можно не указывать, но стоит помнить, что она остаётся действительной, если уже определена у метода родительского класса.

Так же, возможно добавлять новые исключения, являющиеся наследниками от уже объявленных или исключения RuntimeException. Порядок следования таких элементов при переопределении значения не имеет.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Могут ли классы быть статическими?

A

Класс можно объявить статическим за исключением классов верхнего уровня.
Такие классы известны как «вложенные статические классы» (nested static class).

24
Q

Что означает модификатор final? К чему он может быть применим?

A

Модификатор final может применяться к переменным, параметрам методов, полям и методам класса или самим классам.

  • Класс не может иметь наследников;(Следует также отметить, что к abstract-классам нельзя применить модификатор final, т.к. это взаимоисключающие понятия.)
  • Метод не может быть переопределен в классах наследниках;
  • Поле не может изменить свое значение после инициализации;
  • Для ссылочных переменных это означает, что после присвоения объекта, нельзя изменить ссылку на данный объект. Важно: Ссылку изменить нельзя, но состояние объекта изменять можно.
  • Параметры методов не могут изменять своё значение внутри метода;
  • Локальные переменные не могут быть изменены после присвоения им значения.
25
Q

Что такое абстрактные классы? Чем они отличаются от обычных?

A

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

Наследниками абстрактного класса могут быть другие абстрактные классы

Особенности абстрактных классов:

  • Может быть конструктор (для вызовов по цепочке из наследников)
  • Имплементят интерфейсы, но не обязаны реализовывать их методы
  • Не могут быть final
  • Могут содержать static методы
  • Нельзя создать объект
  • Абстрактные методы могут отсутствовать
  • Может содержать метод main()
26
Q

Может ли быть абстрактный класс без абстрактных методов?

A

Класс может быть абстрактным без единого абстрактного метода, если у него указан модификатор abstract.

27
Q

Могут ли быть конструкторы у абстрактных классов? Для чего они нужны?

A

Да. Необходимы для наследников.

В абстрактном классе в Java можно объявить и определить конструкторы. Даже если вы не объявили никакого конструктора, компилятор добавит в абстрактный класс конструктор по умолчанию без аргументов.

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

28
Q

Что такое интерфейсы?
Какие модификаторы по умолчанию имеют поля и методы интерфейсов?

A

Интерфейс – это совокупность методов, определяющих правила взаимодействия
элементов системы.
Другими словами, интерфейс определяет как элементы будут
взаимодействовать между собой.
Ключевое слово interface используется для создания полностью абстрактных классов.
Основное предназначение интерфейса – определять, каким образом можно использовать класс, который его реализует. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не реализует их поведение. Все методы неявно объявляются как public.
Интерфейс также может содержать и поля. В этом случае они автоматически являются
публичными public, статическими static и неизменяемыми final.
Интерфейс нужен чтобы реализовать абстрактный класс. По сути это абстрактный класс, все методы у него абстрактные.
* методы интерфейса являются публичными (public) и абстрактными (abstract),
если имплементировать интерфейс, то наследующий его класс должен будет
реализовать все эти абстрактные методы, в отличии от абстрактного класса;
* поля – public static final;
* есть дефолтный метод;
* методы могут быть static.

29
Q

Какие нововведения появились в интерфейсах с появлением Java 8?

A

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

2) 1) Методы по-умолчанию (default methods):
default void print() {System.out.println(“DEFAULT”)};

2) Статические методы (static methods).
static void print() {(System.out.println(“STATIC”))}

30
Q

Чем интерфейсы отличаются от абстрактных классов?

A
  1. Интерфейс описывает только поведение (методы) объекта, а вот состояний (полей) у него нет (кроме public static final), в то время как у абстрактного класса они могут быть.
  2. Мы можем наследовать только один класс, а реализовать интерфейсов — сколько угодно. Интерфейс может наследовать (extends) другой интерфейс/интерфейсы.
  3. Абстрактные классы используются, когда есть отношение “is-a”, то есть класс-наследник расширяет базовый абстрактный класс, а интерфейсы могут быть реализованы разными классами, вовсе не связанными друг с другом.
  4. Абстрактный класс может реализовывать методы; интерфейс может реализовывать статические методы начиная с 8й версии.
  5. Нет конструктора у интерфейса.

Интерфейс — это план класса или, можно сказать, набор абстрактных методов и статических констант. В интерфейсе каждый метод является открытым и абстрактным, но не содержит конструктора. Таким образом, интерфейс в основном представляет собой группу связанных методов с пустыми телами. Другими словами, интерфейс определяет как элементы будут взаимодействовать между собой.

  • методы интерфейса являются публичными (public) и абстрактными (abstract),
  • поля — public static final.
31
Q

Когда имеет смысл предпочесть абстрактный класс интерфейсу и наоборот?

A

Абстрактный класс лучше, если:
1) Классы-наследники в целом похожи между собой, имеют много общих методов или полей.
2) Общие поля требуют не только модификаторов public static final, но и других (protected, private, не static, не final).

Интерфейс лучше, если:
1) Его будут реализовывать не связанные между собой классы. Например, интерфейс Comparable могут реализовывать классы с совершенно разной функциональностью.
2) Вы хотите “определить функциональность” какого-то класса, но что это за класс и как он это реализует - вам не важно.
3) Вы хотите использовать множественное наследование типа.

32
Q

Может ли один интерфейс наследоваться от другого? От двух других?

A

Да, может. Используется ключевое слово extends

33
Q

Что такое дефолтные методы интерфейсов? Для чего они нужны?

A

Java 8 позволяет добавлять неабстрактные реализации методов в интерфейс, используя ключевое слово default.
Если класс реализует интерфейс, он может, но не обязан, реализовать методы по-умолчанию, уже реализованные в интерфейсе. Класс наследует реализацию по умолчанию. Если некий класс реализует несколько интерфейсов, которые имеют одинаковый метод по умолчанию, то класс должен реализовать метод с совпадающей сигнатурой самостоятельно. Ситуация аналогична, если один интерфейс имеет метод по умолчанию, а в другом этот же метод является абстрактным - никакой реализации по умолчанию классом не наследуется. Метод по умолчанию не может переопределить метод класса java.lang.Object. Помогают реализовывать интерфейсы без страха нарушить работу других классов. Позволяют избежать создания служебных классов, так как все необходимые методы могут быть представлены в самих интерфейсах. Дают свободу классам выбрать метод, который нужно переопределить. Одной из основных причин внедрения методов по умолчанию является возможность коллекций в Java 8 использовать лямбда-выражения.

34
Q

Почему в некоторых интерфейсах вообще не определяют методов?

A

Это так называемые маркерные интерфейсы. Они просто указывают, что класс относится к определенному типу. Примером может послужить интерфейс Clonable, который указывает на то, что класс поддерживает механизм клонирования.

35
Q

Как решается проблема ромбовидного наследования при наследовании интерфейсов при наличии default методов?

A

класс, наследующий конфликтующие интерфейсы, должен явно через super определить, какой именно метод вызвать:
InterfaceB.super.method();

36
Q

Каков порядок вызова конструкторов и блоков инициализации с учётом
иерархии классов?

A

Сначала вызываются все статические блоки в очередности от первого статического блока корневого предка и выше по цепочке иерархии до статических блоков самого класса. Затем вызываются нестатические блоки инициализации корневого предка, конструктор корневого предка и так далее вплоть до нестатических блоков и конструктора самого класса.
Parent static block(s) → Child static block(s) → Grandchild static block(s)

→ Parent non-static block(s) → Parent constructor →

→ Child non-static block(s) → Child constructor →

→ Grandchild non-static block(s) → Grandchild constructor

37
Q

Зачем нужны и какие бывают блоки инициализации?

A

Инициализация - это когда мы впервые задаем переменной какое-либо значение.

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

  • Существуют статические и нестатические блоки инициализации.
  • Блок инициализации выполняется перед инициализацией класса загрузчиком классов или созданием объекта класса с помощью конструктора.
  • Несколько блоков инициализации выполняются в порядке следования в коде класса.
  • Блок инициализации способен генерировать исключения, если их объявления перечислены в throws всех конструкторов класса.
  • Блок инициализации возможно создать и в анонимном классе.
    Статические поля можно инициализировать при объявлении, в статическом или нестатическом блоке инициализации. Нестатические поля можно инициализировать при объявлении, в нестатическом блоке инициализации или в конструкторе.
38
Q

Для чего в Java используются статические блоки инициализации?

A

Статические блоки инициализация используются для выполнения кода, который должен выполняться один раз при инициализации класса загрузчиком классов, в момент предшествующий созданию объектов этого класса при помощи конструктора.

Такой блок (в отличие от нестатических, принадлежащих конкретном объекту класса) принадлежит только самому классу (объекту метакласса Class).

39
Q

Что произойдет, если в блоке инициализации возникнет исключительная ситуация?

A

Для статического блока выбрасывание исключения в явном виде приводит к ошибке
компиляции ExceptionInizialazionError., нестат. – вылетит само исключение.

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

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

Класс не будет инициализирован, если ошибка происходит в статическом блоке и объект класса не будет создан, если ошибка возникает в нестатическом блоке.

40
Q

Какое исключение выбрасывается при возникновении ошибки в блоке
инициализации класса?

A

Если возникшее исключение – наследник Error:
* для статических блоков инициализации будет выброшено
java.lang.ExceptionInInitializerError;
* для нестатических будет проброшено исключение-источник.
Если возникшее исключение – наследник Error, то в обоих случаях будет выброшено
java.lang.Error.
Если исключение java.lang.ThreadDeath (смерть потока), то в этом случае никакое
исключение выброшено не будет.

41
Q

Что такое класс Object?

A

Базовый класс для всех остальных объектов в Java. Любой класс наследуется от Object и, соответственно, наследуют его методы

Все классы являются наследниками суперкласса Object. Это не нужно указывать явно. В результате объект Object может ссылаться на объект любого другого класса.

Рефлексия (от позднелат. reflexio - обращение назад) - это механизм исследования данных о программе во время её выполнения.

42
Q

Какие методы есть у класса Object (перечислить все)? Что они делают?

A
  • equals() - служит для сравнения объектов по значению;
  • hashCode() - возвращает hash-код для объекта;
  • toString() - представления данного объекта в виде строки.
  • getClass() - возвращает класс объекта во время выполнения;
  • clone() - создает и возвращает копию объекта;
  • finalize() - deprecated, вызывается GC перед удалением. (нет гарантии что будет вызван)

Для многопоточки:
- notify() - «размораживает» одну случайную нить
- notifyAll() - «размораживает» все нити данного монитора
- wait() - нить освобождает монитор и «становится на паузу»
- wait(long timeOut) - нить освобождает монитор и «становится на паузу»,принимает максимальное время ожидания в миллисекундах.
- wait(long timeOut, int nanos) - нить освобождает монитор и «становится на паузу»,принимает максимальное время ожидания в миллисекундах, дополнительное время, в диапазоне наносекунд 0-999999.

43
Q

Расскажите про equals

A

Equals – это метод, определенный в Object, который служит для сравнения объектов.
При сравнении объектов при помощи == идет сравнение по ссылкам. При сравнении по
equals() идет сравнение по состояниям объектов (по умолчанию случайным образом, но
есть другие варианты).
По умолчанию ссылки, чтобы его использовать, нужно переопределить (на область в
памяти), т. к. при == сравниваются ссылки, а equals сравнивает состояния:
Свойства equals():
* Рефлексивность: для любой ссылки на значение x, x.equals(x) вернет true;
* Симметричность: для любых ссылок на значения x и y, x.equals(y) должно
вернуть true, тогда и только тогда, когда y.equals(x) возвращает true.
* Транзитивность: для любых ссылок на значения x, y и z, если x.equals(y) и
y.equals(z) возвращают true, тогда и x.equals(z) вернет true;
* Непротиворечивость: для любых ссылок на значения х и у, если несколько раз
вызвать х.equals(y), постоянно будет возвращаться значение true либо постоянно
будет возвращаться значение false при условии, что никакая информация,
используемая при сравнении объектов, не поменялась;
* Совместимость с hashCode(): два тождественно равных объекта должны иметь
одно и то же значение hashCode().
При переопределении equals() обязательно нужно переопределить метод hashCode().
Равные объекты должны возвращать одинаковые хэш коды.

44
Q

Расскажите про hashcode

A

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

Метод hashCode() необходим для вычисления хэш кода переданного в качестве входного параметра объекта. В Java это целое число, в более широком смыле - битовая строка фиксированной длины, полученная из массива произвольной длины. Этот метод реализован таким образом, что для одного и того же входного объекта, хэш код всегда будет одинаковым. Следует понимать, что в Java множество возможных хэш кодов ограничено типом int, а множество объектов ничем не ограничено. Из-за этого, вполне возможна ситуация, что хэш коды разных объектов могут совпасть:

  • если хэш коды разные, то и объекты гарантированно разные;
  • если хэш коды равны, то объекты могут не обязательно равны.
  • для одного и того-же объекта, хеш-код всегда будет одинаковым;
  • если объекты одинаковые, то и хеш-коды одинаковые (но не наоборот).

Общий совет: выбирать поля, которые с большой долью вероятности будут различаться. Для этого необходимо использовать уникальные, лучше всего примитивные поля, например такие как id, uuid. При этом нужно следовать правилу, если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().

45
Q

Каким образом реализованы методы hashCode() и equals() в классе Object?

A
  1. Реализация метода Object.equals() сводится к проверке на равенство двух ссылок:
    public boolean equals(Object obj) {
    return (this == obj);
    }
  2. Реализация метода Object.hashCode() описана как native, т. е. определенной не с
    помощью Java-кода и обычно возвращает адрес объекта в памяти:
    public native int hashCode();

Ситуация, когда у разных объектов одинаковые хеш-коды называется — коллизией. Вероятность возникновения коллизии зависит от используемого алгоритма генерации хеш-кода.

46
Q

Зачем нужен equals(). Чем он отличается от операции ==?

A

Метод equals() - определяет отношение эквивалентности объектов.

При сравнении объектов с помощью == сравнение происходит лишь между ссылками.

При сравнении по переопределённому разработчиком equals() - по внутреннему состоянию объектов.

47
Q

Правила переопределения equals()

A

Использование оператора == для проверки, является ли аргумент ссылкой на указанный объект. Если является, возвращается true. Если сравниваемый объект == null, должно вернуться false.
Использование оператор instanceof и вызова метода getClass() для проверки, имеет ли аргумент правильный тип. Если не имеет, возвращается false.
Приведение аргумента к правильному типу. Поскольку эта операция следует за проверкой instanceof она гарантированно будет выполнена.
Обход всех значимых полей класса и проверка того, что значение поля в текущем объекте и значение того же поля в проверяемом на эквивалентность аргументе соответствуют друг другу. Если проверки для всех полей прошли успешно, возвращается результат true, в противном случае - false.
По окончанию переопределения метода equals() следует проверить: является ли порождаемое отношение эквивалентности рефлексивным, симметричным, транзитивным и непротиворечивым? Если ответ отрицательный, метод подлежит соответствующей правке.

48
Q

Что будет, если переопределить equals() не переопределяя hashCode()? Какие
могут возникнуть проблемы?

A

Нарушится контракт. Классы и методы, которые использовали правила этого контракта могут некорректно работать.

Так для объекта HashMap это может привести к тому, что пара, которая была помещена в Map возможно не будет найдена в ней при обращении к Map, если используется новый экземпляр ключа.

49
Q

Какой контракт между hashCode() и equals()?

A

1) Если два объекта возвращают разные значения hashcode(), то они не могут быть равны
2) Если equals объектов true, то и хэшкоды должны быть равны.
3) Переопределив equals, всегда переопределять и hashcode.

  • Вызов метода hashCode один и более раз над одним и тем же объектом должен возвращать одно и то же хэш-значение, при условии что поля объекта, участвующие в вычислении значения, не изменялись.
  • Вызов метода hashCode над двумя объектами должен всегда возвращать одно и то же число, если эти объекты равны (вызов метода equals для этих объектов возвращает true).
  • Вызов метода hashCode над двумя неравными между собой объектами должен возвращать разные хэш-значения. Хотя это требование и не является обязательным, следует учитывать, что его выполнение положительно повлияет на производительность работы хэш-таблиц.
50
Q

Для чего нужен метод hashCode()?

A

Метод hashCode() необходим для вычисления хэш кода переданного в качестве входного параметра объекта.

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

Следует понимать, что в Java множество возможных хэш кодов ограничено типом int, а множество объектов ничем не ограничено. Из-за этого, вполне возможна ситуация, что хэш коды разных объектов могут совпасть:

  • если хэш коды разные, то и объекты гарантированно разные;
  • если хэш коды равны, то объекты могут не обязательно равны.

В случае, если hashCode() не переопределен, то будет выполнятся его реализация по
умолчанию из класса Object: для разных объектов будет разный хеш-код.
Значение int может быть в диапазоне 232, при переопределении хеш-кода можно
использовать отрицательное значение.

51
Q

Правила переопределения метода hashcode().

A

1) Если хеш-коды разные, то и входные объекты гарантированно разные.

2) Если хеш-коды равны, то входные объекты не всегда равны.

3) При вычислении хэш-кода следует использовать те же поля, которые сравниваются в equals и которые не вычисляются на основе других значений.

  • вызов метода hashCode один и более раз над одним и тем же объектом должен возвращать одно и то же хэш-значение, при условии что поля объекта, участвующие в вычислении значения, не изменялись.
  • вызов метода hashCode над двумя объектами должен всегда возвращать одно и то же число, если эти объекты равны (вызов метода equals для этих объектов возвращает true).
  • вызов метода hashCode над двумя неравными между собой объектами должен возвращать разные хэш-значения. Хотя это требование и не является обязательным, следует учитывать, что его выполнение положительно повлияет на производительность работы хэш-таблиц.
52
Q

Есть ли какие-либо рекомендации о том, какие поля следует использовать при
подсчете hashCode()?

A

Выбирать поля, которые с большой долью вероятности будут различаться.

Для этого необходимо использовать уникальные, лучше всего примитивные поля, например такие как id, uuid.

При этом нужно следовать правилу, если поля задействованы при вычислении hashCode(), то они должны быть задействованы и при выполнении equals().

53
Q

Могут ли у разных объектов быть одинаковые hashCode()?

A

Да, могут. Метод hashCode() не гарантирует уникальность возвращаемого значения. Ситуация, когда у разных объектов одинаковые хэш коды называется коллизией. Вероятность возникновения коллизии зависит от используемого алгоритма генерации хэш кода.

54
Q

Почему нельзя реализовать hashcode() который будет гарантированно
уникальным для каждого объекта?

A

В Java множество возможных хэш кодов ограничено типом int, а множество объектов ничем не ограничено.

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

55
Q

Есть класс Point{int x, y;}. Почему хэш-код в виде 31 * x + y предпочтительнее
чем x + y?

A

Множитель создает зависимость значения хэш-кода от очередности обработки полей, а это дает гораздо лучшую хэш-функцию.

56
Q

Чем a.getClass().equals(A.class) отличается от a instanceOf A.class

A

getClass() получает только класс, а оператор instanceof проверяет является ли объект экземпляром класса или его потомком