ООП в Java
Java — объектно-ориентированный язык с одиночным наследованием классов и множественной реализацией интерфейсов. Большая часть вопросов на собеседовании крутится не вокруг определений «инкапсуляция, наследование, полиморфизм», а вокруг одной границы: что решает компилятор на этапе компиляции, а что — JVM во время выполнения. Перегрузка выбирается по типам аргументов при компиляции; переопределение — по фактическому типу объекта в рантайме. Не различая эти два механизма, легко объяснить @Override неверно и провалить вопрос про static-метод.
Вторая опора темы — контракты и связи между типами: чем abstract-класс (хранит состояние, наследуется один) отличается от interface (чистый контракт, реализуется много), как this и super адресуют текущий и родительский объект, какие бывают вложенные классы и почему одни держат ссылку на внешний экземпляр, а другие нет. Ниже — карта темы по слоям.
Карта темы
- Переопределение методов — подкласс заменяет метод родителя с той же сигнатурой; версию выбирает JVM по фактическому типу объекта.
- Перегрузка методов — несколько методов с одним именем и разными параметрами; нужный выбирает компилятор по типам аргументов.
- Абстрактный класс против интерфейса —
abstract-класс хранит состояние и наследуется один,interface— контракт, которых реализуется много. - Ключевое слово super — доступ к родительской версии метода и вызов конструктора суперкласса первой строкой.
- Ключевое слово this — ссылка на текущий объект, разрешение затенения поля параметром и цепочка конструкторов.
- Вложенные классы — статические вложенные, внутренние, локальные и анонимные; кто держит ссылку на внешний объект.
- Маркерные интерфейсы — пустой интерфейс-метка вроде
SerializableиCloneable, проверяемый в рантайме. - Инициализация двойными скобками — анти-паттерн
{{ ... }}: анонимный подкласс плюс блок инициализатора и скрытая утечка.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
| Считать, что перегрузка выбирается в рантайме, как переопределение | Перегрузка фиксируется при компиляции по типу ссылки, а не по типу объекта |
| Думать, что достаточно другого типа возврата, чтобы перегрузить метод | Не компилируется — перегрузку задаёт только список параметров |
Ждать полиморфизма от static-метода в подклассе | Он не переопределяет, а скрывает родительский; вызов идёт по типу ссылки |
Ставить super(...) или this(...) не первой строкой конструктора | Ошибка компиляции — оба обязаны быть первой инструкцией |
| Считать, что статический вложенный класс видит поля внешнего экземпляра | У него нет ссылки на внешний объект — только у нестатического внутреннего |
| Ждать от маркерного интерфейса методов | Он пуст; отсутствие нужной метки (Cloneable) → исключение в рантайме |
| Использовать double-brace init ради «краткости» | Лишний class-файл плюс скрытая ссылка this$0 на внешний объект → утечка |
Значение для собеседований
ООП — база почти любого Java-интервью, но проверяют не заученные «четыре принципа», а модель того, кто и когда принимает решение о вызове. Кандидат, который чётко разводит «компилятор выбирает перегрузку по типу ссылки» и «JVM выбирает переопределение по типу объекта», сразу звучит уверенно.
Что обычно проверяют:
- Переопределение (та же сигнатура, рантайм, полиморфизм) против перегрузки (разные параметры, компиляция).
- Почему
private,staticиfinalметоды не переопределяются, и чтоstaticлишь скрывается. - Разницу
abstract-класса иinterface: состояние, число наследуемых типов,default-методы с Java 8. - Роли
thisиsuper, правило «первой строки» дляthis(...)/super(...). - Виды вложенных классов и кто несёт ссылку на внешний объект.
Типичный неверный ответ: «static-метод в подклассе переопределяет родительский». Это открывает разговор о сокрытии (method hiding): вызов такого метода разрешается по типу ссылки при компиляции, поэтому полиморфизма нет — в отличие от настоящего переопределения экземпляра.