Java Core Flashcards

1
Q

Чем различаются JRE, JVM и JDK?

A
  • JVM (Java Virtual Machine) выполняет байт-код Java.
  • JRE (Java Runtime Environment) - минимальная среда для исполнения Java-приложений, включает в себя JVM и стандартные библиотеки.
  • JDK (Java Development Kit) - среда разработки на Java, включает JRE, компилятор, библиотеки и инструменты разработчика.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Какие существуют модификаторы доступа?

A
  • private: доступ только внутри класса.
  • default/package-private: доступ внутри пакета (модификатор по умолчанию).
  • protected: доступ внутри пакета и в наследниках.
  • public: общий доступ.
  • Последовательность уровней закрытости: public, protected, default, private.
  • Возможно изменение модификаторов в сторону большей видимости при наследовании (для поддержания соответствия принципу подстановки Барбары Лисков).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

О чем говорит ключевое слово final?

A
  • Запрещает наследование для класса.
  • Препятствует переопределению метода.
  • Позволяет переменным быть инициализированными только один раз.
  • Запрещает изменение значений параметров метода и локальных переменных после их инициализации.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Какими значениями инициализируются переменные по умолчанию?

A

Значения по умолчанию:
- byte: (byte)0
- short: (short)0
- int: 0
- long: 0L
- float: 0f
- double: 0d
- char: ‘\u0000’
- boolean: false
- Объекты (включая String): null

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

Что вы знаете о функции main()?

A

Функция main():
- Точка входа в программу.
- Может быть несколько main() в приложении.
- Отсутствие main() приводит к ошибке при запуске.
- Синтаксис:
public static void main(String[] args) {}

String[] args представляет собой механизм, с помощью которого можно передавать в Java-приложение данные прямо при его запуске. Это может быть полезно во многих случаях, например, если необходимо указать при запуске некоторые параметры настройки приложения, пути к файлам, значения переменных и т.д.

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

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

A
  • &: Логическое AND (И)
  • &&: Сокращённое AND
  • |: Логическое OR (ИЛИ)
  • ||: Сокращённое OR
  • ^: Логическое XOR (исключающее OR (ИЛИ))
  • !: Логическое унарное NOT (НЕ)
  • &=: AND с присваиванием
  • |=: OR с присваиванием
  • ^=: XOR с присваиванием
  • ==: Равно
  • !=: Не равно
  • ?: Тернарный (троичный) условный оператор
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Что такое тернарный оператор выбора?

A

Тернарный оператор выбора (?:) - замена конструкции if-then-else. Формат: условие ? выражение1 : выражение2. Если условие истинно, возвращается выражение1, иначе - выражение2. Оба операнда должны иметь совместимые типы.

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

Какие побитовые операции вы знаете?

A

~: Побитовый унарный оператор NOT;
&: Побитовый AND;
&=: Побитовый AND с присваиванием;
|: Побитовый OR;
|=: Побитовый OR с присваиванием;
^: Побитовый исключающее XOR;
^=: Побитовый исключающее XOR с присваиванием;
»: Сдвиг вправо (деление на 2 в степени сдвига);
»=: Сдвиг вправо с присваиванием;
»>: Сдвиг вправо без учёта знака;
»>=: Сдвиг вправо без учёта знака с присваиванием;
«: Сдвиг влево (умножение на 2 в степени сдвига);
«=: Сдвиг влево с присваиванием.

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

Где и для чего используется модификатор abstract?

A
  • Применяется к классам и методам.
  • Абстрактный класс не может иметь экземпляров и используется в качестве предка для других классов.
  • Абстрактный метод не имеет реализации и должен быть переопределен в подклассах.
  • Позволяет определить шаблон объекта, оставляя детали реализации для подклассов.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

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

A
  • Ключевое слово interface используется для создания полностью абстрактных классов.
  • Определяет, как можно использовать класс, который его реализует.
  • Методы в интерфейсе неявно объявляются как public.
  • С начала Java 8 в интерфейсах можно иметь методы с реализацией по умолчанию (default) и статические методы (static).
  • Поля в интерфейсе являются public, static и final.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Чем абстрактный класс отличается от интерфейса? В каких случаях следует использовать абстрактный класс, а в каких интерфейс?

A
  • Класс может реализовать несколько интерфейсов, но наследоваться только от одного класса.
  • Абстрактные классы используются при наличии отношения “является” (is-a). Интерфейсы могут быть реализованы классами, которые не связаны между собой.
  • Абстрактные классы предоставляют средства для избежания повторения кода и частичной реализации поведения. Интерфейсы описывают контракты и семантику класса.
  • Интерфейсы позволяют создавать структуры типов без иерархии.
  • Абстрактные классы содержат частичную реализацию, которая расширяется в подклассах. Интерфейсы могут содержать только сигнатуры методов и константы.
    НО: начиная Java 8 в интерфейсах можно иметь методы с реализацией по умолчанию (default) и статические методы (static).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

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

A

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

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

Почему нельзя объявить метод интерфейса с модификатором final?

A

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

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

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

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

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

A
  • Сначала вызываются все статические блоки сверху вниз по иерархии классов.
  • Затем вызываются нестатические блоки инициализации и конструкторы сверху вниз по иерархии классов.

Пример:
- Сначала вызываются статические блоки: Parent, Child, Grandchild.
- Затем нестатические блоки и конструкторы: Parent, Child, Grandchild.

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

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

A
  • Представляют код внутри класса, заключенный в фигурные скобки, вне методов или конструкторов.
  • Бывают статическими и нестатическими.
  • Выполняются перед инициализацией класса или созданием объекта.
  • Может быть несколько и выполняются в порядке следования.
  • Могут генерировать исключения, если их объявления перечислены в throws конструкторов.
  • Могут существовать в анонимных классах.
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

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

A

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

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

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

A
  • Для нестатических блоков инициализации требуется объявление исключения в throws всех конструкторах класса, иначе - ошибка компиляции.
  • В случае статического блока выбрасывание исключения явно приводит к ошибке компиляции.
  • В остальных случаях взаимодействие с исключениями аналогично другим местам: класс не будет инициализирован (статический блок) или объект не создан (нестатический блок).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

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

A
  • Если исключение является наследником RuntimeException:
    • Для статических блоков - ExceptionInInitializerError.
    • Для нестатических - проброшено исключение-источник.
  • Если исключение является наследником Error, в обоих случаях - Error.
  • Исключение java.lang.ThreadDeath (смерть потока) не выбрасывается явно в данном контексте.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

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

A
  • Может быть перегружен: два статических метода могут иметь одинаковое имя, если количество их параметров или типов различается.
  • Не может быть переопределён, так как выбор вызываемого статического метода происходит при раннем связывании (на этапе компиляции). Синтаксически переопределение статического метода возможно, но всегда будет вызываться метод родителя.
    Рекомендуется обращаться к статическим полям и методам через имя класса, а не объект.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

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

A

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

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

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

A

При переопределении метода в Java нельзя сузить модификатор доступа и изменить тип возвращаемого значения (кроме ситуаций, когда типы совместимы).

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

Возможно ли при переопределении метода изменить:
- модификатор доступа;
- возвращаемый тип;
- тип аргумента или их количество;
- имена аргументов или их порядок;

Убирать, добавлять, изменять порядок следования элементов секции throws?

A
  • нельзя сужать модификатор доступа, т.к. это приведёт к нарушению принципа подстановки Барбары Лисков.
    Например, если метод в суперклассе имеет модификатор protected, в подклассе его нельзя переопределить с модификатором private. Можно усилить уровень доступа (например, с protected на public), но не наоборот;
  • не рекомендуется изменять возвращаемый тип. Но можно использовать подтип возвращаемого типа. Это означает, что подкласс может возвращать подкласс или подтип возвращаемого типа, указанного в суперклассе. Но нельзя изменить возвращаемый тип на его супертип;
  • нельзя изменять тип аргумента или их количество. Метод в подклассе должен иметь точно такую же сигнатуру (типы аргументов и их количество), как и метод в суперклассе;
  • можно изменить имена аргументов без нарушения правил переопределения. Однако порядок аргументов должен оставаться тем же;
  • при переопределении метода можно расширить (добавить подтипы) секцию throws (исключения), но нельзя сужать ее. Если суперкласс объявляет, что метод может бросать исключение определенного типа, подкласс может бросать исключение этого типа или его подтип.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

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

A

Для доступа к переопределенным методам родительского класса в Java используется ключевое слово super.

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

Можно ли объявить метод абстрактным и статическим одновременно?

A

Нельзя. Модификатор abstract говорит, что метод будет реализован в другом классе, а static наоборот указывает, что этот метод будет доступен по имени класса.

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

В чем разница между членом экземпляра класса и статическим членом класса?

A

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

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

Где разрешена инициализация статических/нестатических полей?

A

Статические поля можно инициализировать при объявлении, в статическом или нестатическом блоке инициализации.
Нестатические поля можно инициализировать при объявлении, в нестатическом блоке инициализации или в конструкторе.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
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
31
Q

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

A

Вложенные классы (Nested class) в Java делятся на четыре категории и их использование зависит от ситуации:
- 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
32
Q

Что такое «статический класс»?

A

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

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

Какие существуют особенности использования вложенных классов: статических и внутренних? В чем заключается разница между ними?

A

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

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

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

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

A

Local inner class (Локальный класс) - это вложенный класс, объявленный внутри блока кода. Он имеет следующие особенности:

  • Виден только в пределах блока, в котором объявлен.
  • Не может быть объявлен как private/public/protected или static.
  • Не может содержать статических методов или классов, но может иметь финальные статические поля.
  • Имеет доступ к полям и методам обрамляющего класса.
  • Может обращаться к локальным переменным и параметрам метода, если они объявлены с модификатором final.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

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

A

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

36
Q

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

A

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

37
Q

Для чего используется оператор assert?

A

Оператор assert в Java используется для проверки предположений о значениях данных в произвольном месте программы. Утверждения упрощают локализацию ошибок, проверяя значения данных и автоматически сигнализируя о некорректных значениях. Утверждения рекомендуется оставлять включенными во время разработки и тестирования, но отключать в релиз-версиях программы. Оператор assert реализован в форме assert [выражение типа boolean]; или assert [выражение типа boolean] : [детальное сообщение];. Неправильное использование assert может изменить поведение программы, поэтому внутри assert не рекомендуется вызывать методы, изменяющие состояние программы или внешнего окружения.

38
Q

Что такое Heap и Stack память в Java? Какая разница между ними?

A

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

Stack (стек) представляет область хранения данных в оперативной памяти, используемую для локальных переменных методов. Работает по принципу Last-In-First-Out (LIFO).

Различия:

  1. Куча используется всеми частями приложения, стек - только одним потоком исполнения.
  2. Объекты всегда хранятся в куче, а в стеке - только ссылки на них.
  3. Объекты в куче доступны из любой точки программы, в то время как стековая память - только локальным переменным методов.
  4. Память стека существует во время выполнения программы, в то время как куча существует с начала до конца работы программы.
  5. Переполнение памяти стека вызывает StackOverflowError, а переполнение памяти кучи - OutOfMemoryError.
  6. Размер памяти стека намного меньше размера кучи.
  7. Стековая память работает быстрее из-за простоты распределения памяти.
  8. Начальный и максимальный размер памяти в куче определяются с помощью опций -Xms и -Xmx, размер памяти стека - с помощью опции -Xss.
39
Q

Верно ли утверждение, что примитивные типы данных всегда хранятся в стеке, а экземпляры ссылочных типов данных в куче?

A

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

  1. Примитивные типы данных в стеке:
    Когда примитивные переменные объявляются внутри метода, они обычно хранятся в стеке памяти. Стек используется для хранения локальных переменных и управления вызовами методов.
  2. Примитивные типы данных в куче:
    Однако примитивные типы данных также могут храниться в куче, когда они являются частью объектов (например, в массивах или пользовательских классах).
  3. Экземпляры ссылочных типов в куче:
    Экземпляры объектов ссылочных типов данных (классы, интерфейсы, массивы) всегда хранятся в куче.

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

40
Q

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

A

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

41
Q

Для чего нужен сборщик мусора?

A

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

Существует два основных подхода к обнаружению мусора: подсчет ссылок и трассировка. В Java используется трассировочный подход, где сборщик мусора исследует дерево объектов, начиная с корневых точек (GC Root), и определяет, какие объекты являются мусором.

Для освобождения памяти от мусора применяются различные методы, такие как копирующий сборщик и метод “mark-and-sweep”. HotSpot VM в Java использует комбинированный подход Generational Garbage Collection, который адаптирован для эффективной работы с особенностями создания и использования объектов в Java приложениях.

42
Q

Как работает сборщик мусора?

A

Сборщик мусора в Java освобождает память, удаляя неиспользуемые объекты. Объекты, на которые нет ссылок из корневых точек (GC Root), считаются мусором и удаляются. Процесс сборки мусора автоматически выполняется виртуальной машиной Java, гарантируя, что память эффективно используется.

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

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

43
Q

Какие разновидности сборщиков мусора реализованы в виртуальной машине HotSpot?

A

В виртуальной машине HotSpot для Java реализованы четыре сборщика мусора:

  1. Serial (последовательный):
    Простой вариант, подходит для небольших приложений с низкими требованиями к задержкам. Используется опцией -XX:+UseSerialGC.
  2. Parallel (параллельный):
    Наследует подход последовательного сборщика, добавляя параллелизм в некоторые операции. Автоматически подстраивается под параметры производительности. Включается опцией -XX:+UseParallelGC.
  3. Concurrent Mark Sweep (CMS):
    Направлен на снижение максимальных задержек, частично выполняя сборку параллельно с основными потоками приложения. Подходит для работы с большими объемами данных. Включается опцией -XX:+UseConcMarkSweepGC.
  4. Garbage-First (G1):
    Заменяет CMS, предназначен для серверных приложений, работающих на многопроцессорных серверах и управляющих большими объемами данных. Включается опцией -XX:+UseG1GC.
44
Q

Опишите алгоритм работы какого-нибудь сборщика мусора, реализованного в виртуальной машине HotSpot.

A

Serial Garbage Collector (последовательный сборщик мусора) в HotSpot VM работает по принципу копирования. В Young generation объекты создаются в области Eden, а затем копируются в Survivor spaces и, при необходимости, в Old generation. После каждого прохода освобождается память, но этот процесс прерывает работу приложения.

В Old generation используется mark-sweep-compact алгоритм. Он помечает, очищает и уплотняет память для эффективного выделения новых объектов. Однако, такой метод может вызывать длительные паузы в приложении, что может быть недопустимо для некоторых случаев.

Serial GC подходит для небольших приложений, но может вызывать задержки из-за прерывания работы приложения в процессе сборки мусора.

45
Q

Что такое «пул строк»?

A

Пул строк в Java – это коллекция строк, хранящаяся в Heap.

Основные моменты:
- Пул строк экономит память благодаря неизменяемости строк в Java и интернированию;
- Создание строки с использованием “” может вернуть ссылку из пула или создать новую строку в пуле;
- Оператор new создает новый объект String, и метод intern() используется для помещения строки в пул или получения ссылки из него;
- Пул строк представляет собой реализацию паттерна “Приспособленец” (Flyweight).

46
Q

Что такое finalize()? Зачем он нужен?

A

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

Важные моменты:

  • finalize() вызывается перед удалением объекта сборщиком мусора;
  • Переопределяя finalize(), можно определить действия по корректному удалению объекта;
  • Этот метод не гарантирует вызова, и приложение может завершиться до сборки мусора;
  • Использование finalize() может вызвать антипаттерн “возрождение” объекта, ограниченного однократным вызовом.
47
Q

Что произойдет со сборщиком мусора, если выполнение метода finalize() требует ощутимо много времени, или в процессе выполнения будет выброшено исключение?

A

Виртуальная машина Java создает отдельный поток Finalizer для вызова методов finalize(). Если выполнение finalize() занимает много времени или выбрасывает исключение, это не повлияет на работу сборщика мусора. Вызов finalize() происходит в потоке Finalizer, и зависание или выбрасывание исключения в этом процессе не остановит сборку мусора. Это гарантирует, что объекты без метода finalize() будут удаляться, даже если есть проблемы с выполнением finalize() у других объектов.

48
Q

Чем отличаются final, finally и finalize()?

A
  • final - модификатор, применяемый к классам, методам, полям, локальным переменным и параметрам, предотвращающий их изменение или переопределение.
  • finally - блок кода, используемый в структуре try-catch-finally. Код внутри finally выполняется всегда, независимо от того, было ли исключение или нет.
  • finalize() - метод, вызываемый сборщиком мусора перед удалением объекта. Его использование не рекомендуется из-за неопределенности времени вызова и потенциальных проблем с производительностью.
49
Q

Расскажите про приведение типов. Что такое понижение и повышение типа?

A

Приведение типов в Java — это процесс преобразования значения переменной одного типа в значение другого типа. В Java существует тождественное, расширяющее (повышающее), сужающее (понижающее) приведение, а также приведение объектных типов. При приведении примитивных типов данных, необходимо учитывать потенциальные потери данных при сужающем приведении. Для объектных типов используется оператор instanceof для проверки возможности приведения. Важно знать, что приведение ссылочных типов изменяет только тип ссылки, не влияя на сам объект.

50
Q

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

A

ClassCastException в Java выбрасывается, когда происходит ошибка приведения типа. Это происходит, когда попытка привести объект к типу, который он не может иметь. Например, при попытке совершить недопустимое сужающее приведение объекта к классу, который не является его типом или типом его предка. Учитывайте возможные исключения при работе с приведением типов и используйте оператор instanceof для проверки перед приведением.

51
Q

Что такое литералы?

A

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

52
Q

Что такое autoboxing («автоупаковка») в Java и каковы правила упаковки примитивных типов в классы-обертки?

A

Автоупаковка - это механизм неявной инициализации объектов классов-оберток (Byte, Short, Integer, Long, Float, Double, Character, Boolean) значениями соответствующих им исходных примитивных типов (byte, short, int…), без явного использования конструктора класса.

Правила упаковки примитивных типов включают соответствие типов, возможность неявного расширения/сужения типов при автоупаковке констант, и особенности для целочисленных классов-оберток в диапазоне -128 … +127, которые кэшируются JVM.

53
Q

Какие есть особенности класса String?

A
  • Неизменяемый (immutable) и финализированный тип данных;
  • Строки-литералы и интернированные объекты хранятся в пуле строк;
  • Объект String можно создать с использованием двойных кавычек;
  • Оператор + применяется для конкатенации строк;
  • Начиная с Java 7, строки могут использоваться в конструкции switch.

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

54
Q

Почему String неизменяемый и финализированный класс?

A

String является неизменяемым и финализированным классом по следующим причинам:

  • Неизменяемость строки поддерживает пул строк, что экономит память и позволяет интернировать строки.
  • Безопасность: если строки были бы изменяемыми, это могло бы представлять угрозу безопасности приложения.
  • Неизменяемость обеспечивает безопасность в многопоточной среде без необходимости синхронизации.
  • Строки используются classloader, и неизменяемость гарантирует правильность загрузки класса.
  • Кэширование hashCode() при создании строки обеспечивает более эффективное использование в HashMap.

Важное: Использование неизменяемых строк также способствует производительности и улучшает безопасность в различных аспектах приложения.

55
Q

Почему char[] предпочтительнее String для хранения пароля?

A

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

56
Q

Почему строка является популярным ключом в HashMap в Java?

A

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

57
Q

Что делает метод intern() в классе String?

A

Метод intern() в классе String используется для сохранения строки в пуле строк или получения ссылки, если строка уже присутствует в пуле. Это позволяет эффективнее управлять памятью и сравнивать строки.

58
Q

Можно ли использовать строки в конструкции switch?

A

Да, начиная с Java 7, в операторе switch можно использовать строки. Строки чувствительны к регистру, и для сравнения используется метод equals(). Компилятор Java 7 формирует более эффективный байткод для строк в switch по сравнению со сцепленными условиями if-else.

59
Q

Какая основная разница между String, StringBuffer, StringBuilder?

A

Основная разница между String, StringBuffer и StringBuilder заключается в их изменяемости.
- String неизменяем,
- StringBuffer изменяем и синхронизирован,
- StringBuilder изменяем, но не синхронизирован, что делает его более эффективным в непотокобезопасных сценариях.

60
Q

Что такое класс Object? Какие в нем есть методы?

A

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

  • public boolean equals(Object obj) – служит для сравнения объектов по значению;
  • int hashCode() – возвращает hash код для объекта;
  • String toString() – возвращает строковое представление объекта;
  • Class getClass() – возвращает класс объекта во время выполнения;
  • protected Object clone() – создает и возвращает копию объекта;
  • void notify() – возобновляет поток, ожидающий монитор;
  • void notifyAll() – возобновляет все потоки, ожидающие монитор;
  • void wait() – остановка вызвавшего метод потока до момента пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
  • void wait(long timeout) – остановка вызвавшего метод потока на определённое время или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
  • void wait(long timeout, int nanos) – остановка вызвавшего метод потока на определённое время или пока другой поток не вызовет метод notify() или notifyAll() для этого объекта;
  • protected void finalize() – может вызываться сборщиком мусора в момент удаления объекта при сборке мусора.
61
Q

Дайте определение понятию «конструктор».

A

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

62
Q

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

A

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

63
Q

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

A

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

64
Q

Где и как вы можете использовать приватный конструктор?

A

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

65
Q

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

A
  • Классы-загрузчики в Java обеспечивают динамическую загрузку классов во время выполнения.
  • Существует три основных загрузчика: базовый, загрузчик расширений и системный (или приложения).
  • Загрузчики иерархические, и перед загрузкой класса делегируют запрос родительскому загрузчику.
  • Процесс загрузки класса включает в себя три этапа: Loading, Linking (bytecode verification, class preparation, resolving) и Initialization.
  • Динамическая загрузка классов позволяет экономить ресурсы, выполняя загрузку только по мере необходимости.
  • Программируемые загрузчики дают контроль над процессом загрузки и атрибутами безопасности.
  • Множественные пространства имен обеспечивают изоляцию загруженных классов.
66
Q

Что такое Reflection?

A

Рефлексия (Reflection) в Java - это механизм получения информации о программе во время её выполнения. Java Reflection API предоставляет возможности, такие как определение класса объекта, получение информации о модификаторах класса, полях, методах, создание экземпляра класса и другие.

67
Q

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

A

Метод equals() в Java используется для определения отношения эквивалентности между объектами, в отличие от операции ==, которая сравнивает лишь ссылки на объекты. equals() позволяет сравнивать объекты по их внутреннему состоянию.

68
Q

Если вы хотите переопределить equals(), какие условия должны выполняться?

A

Для корректной переопределения метода equals() в Java необходимо соблюсти следующие условия:

  1. Рефлексивность:
    x.equals(x) должно быть true для любого ненулевого объекта x.
  2. Симметричность:
    Если x.equals(y) возвращает true, то и y.equals(x) должно возвращать true.
  3. Транзитивность:
    Если x.equals(y) возвращает true и y.equals(z) возвращает true, то и x.equals(z) должно возвращать true.
  4. Согласованность:
    Повторные вызовы x.equals(y) должны возвращать одинаковые значения, если объекты не изменялись.
  5. Сравнение с null:
    x.equals(null) должно возвращать false.

Дополнительно:

  • Переопределение equals() также должно быть сопровождено переопределением метода hashCode() для соблюдения контракта, гарантирующего корректное функционирование коллекций, таких как HashMap.
  • Обычно equals() сравнивает поля объектов, а также учитывает их типы, чтобы избежать ClassCastException.
  • Переопределение equals() включает в себя проверку на null, сравнение типов и сравнение каждого поля объекта.
  • При переопределении equals() рекомендуется использовать аннотацию @Override для явного указания намерения переопределения метода из суперкласса.
69
Q

Какими свойствами обладает порождаемое equals() отношение эквивалентности?

A
  1. Рефлексивность:
    Для любой ссылки x, x.equals(x) вернет true.
  2. Симметричность:
    Для любых ссылок x и y, x.equals(y) вернет true тогда и только тогда, когда y.equals(x) вернет true.
  3. Транзитивность:
    Для любых ссылок x, y и z, если x.equals(y) и y.equals(z) вернут true, то x.equals(z) также вернет true.
  4. Непротиворечивость:
    Результат x.equals(y) постоянен при неизменных данных объектов x и y.
  5. Сравнение с null:
    Для любой ненулевой ссылки x, x.equals(null) должен вернуть false.

Дополнительно:

  • Переопределение метода hashCode() необходимо для соблюдения контракта и корректной работы с коллекциями.
  • Переопределение equals() должно учитывать типы объектов и избегать ClassCastException.
  • Реализация должна быть эффективной и не вызывать исключения.
70
Q

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

A
  1. Использование ==:
    Проверка, является ли аргумент ссылкой на указанный объект. Возвращается true, если да, и false, если аргумент == null.
  2. Использование getClass():
    Проверка, имеет ли аргумент правильный тип. Если не имеет, возвращается false.
  3. Приведение типа:
    Приведение аргумента к правильному типу.
  4. Проверка полей:
    Обход всех значимых полей класса, проверка их эквивалентности между текущим объектом и аргументом.
  5. Проверка отношения эквивалентности:
    Убедиться в рефлексивности, симметрии, транзитивности и непротиворечивости порождаемого отношения.

Дополнительно:

  • Переопределение hashCode() для корректной работы с коллекциями.
  • Внимание к эффективности, избегание исключений и проверка на null.
  • Учёт особенностей типов данных и избежание ClassCastException.
71
Q

Какая связь между hashCode() и equals()?

A
  • equals():
    Метод сравнения объектов по содержимому.
  • hashCode():
    Метод генерации числового кода (хэш-кода) объекта.

Связь:
- Объекты, равные согласно equals(), должны иметь одинаковый hashCode().
- Разные объекты могут иметь одинаковый hashCode, но это должно редко приводить к сравнению через equals().

Важно:
- Правильная реализация обоих методов обеспечивает корректное функционирование объектов в коллекциях (например, в HashMap).
- Неравенство по equals() обязательно влечет за собой различные hashCode, но обратное не всегда верно.

72
Q

Если equals() переопределен, есть ли какие-либо другие методы, которые следует переопределить?

A

Равные объекты должны возвращать одинаковые хэш коды. При переопределении equals() нужно обязательно переопределять и метод hashCode().

73
Q

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

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

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

A
  • Метод Object.equals() в классе Object сводится к проверке на равенство ссылок с помощью оператора ==.
  • Метод Object.hashCode() в классе Object обычно возвращает адрес объекта в памяти и реализован как native.
75
Q

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

A

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

76
Q

Каковы правила переопределения метода Object.hashCode()?

A
  1. Равные объекты должны иметь одинаковый хэш код.
  2. Переопределение hashCode() должно использовать те же поля, что и equals().
  3. Если equals() возвращает true для двух объектов, их hashCode() должны быть равными.
  4. Нельзя гарантировать уникальность хэш кодов для разных объектов.
77
Q

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

A
  1. Используйте поля, которые с большой вероятностью различаются.
  2. Используйте уникальные и лучше примитивные поля (например, id, uuid).
  3. Если поле участвует в hashCode(), оно должно участвовать и в equals().
78
Q

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

A

Могут. hashCode() не гарантирует уникальность. Одинаковые значения - коллизия. Вероятность коллизий зависит от алгоритма.

79
Q

Если у класса Point{int x, y;} реализовать метод
equals(Object that) {
return this.x == that.x && this.y == that.y;
},
но сделать хэш код в виде
int hashCode() {
return x;
},
то будут ли корректно такие точки помещаться и извлекаться из HashSet?

A

Нет, не будет корректно. Одинаковый хэш код для точек с одинаковым x приведет к вырождению хэш таблицы в список. Коллизии будут разрешаться по equals(), что замедлит производительность.

80
Q

Могут ли у разных объектов (ref0 != ref1) быть ref0.equals(ref1) == true?

A

Да, могут. Для этого необходимо переопределить метод equals() в классе объектов. Если используется Object.equals(), то равенство устанавливается только для ссылок на один и тот же объект.

81
Q

Могут ли у разных ссылок на один объект (ref0 == ref1) быть ref0.equals(ref1) == false?

A

Да, могут. Это возможно, если метод equals() реализован некорректно и не соблюдает свойство рефлексивности.

82
Q

Можно ли так реализовать метод equals(Object that) {
return this.hashCode() == that.hashCode()
}?

A

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

83
Q

В equals() требуется проверять, что аргумент equals(Object that) такого же типа что и сам объект. В чем разница между this.getClass() == that.getClass() и that instanceof MyClass?

A

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

this.getClass() == that.getClass() сравнивает два класса на точную идентичность, не учитывая подклассы.

Разница заключается в том, что instanceof учитывает подклассы, в то время как getClass() сравнивает классы строго. В контексте реализации equals(), для корректного сравнения типов следует использовать instanceof.

84
Q

Можно ли реализовать метод equals() класса MyClass вот так:

class MyClass {
public boolean equals(MyClass that) {
return this == that;
}
}?

A

Можно реализовать метод так, но он будет перегружать, а не переопределять метод equals() класса Object. Для корректной переопределенной версии следует использовать сигнатуру equals(Object obj).

85
Q

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

A

Хэш-код в виде 31 * x + y предпочтителен, потому что 31 - простое число, и произведение обеспечивает эффективное распределение значений хэш-кода, уменьшая вероятность коллизий. Это также обеспечивает различность хэш-кодов для объектов с разными значениями x и y, а также устраняет нечетные результаты в случае переполнения.