Вопросы по Java на собеседовании: ядро языка
Ядро языка спрашивают на каждом собесе Java, и обычно с одних и тех же мест: пул строк, контракт equals и hashCode, проверяемые исключения. Эти вопросы выглядят школьными ровно до уточняющего «а почему».
Из чего состоит тема
Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.
- Типы, обёртки, String25
- ООП и полиморфизм22
- Records, sealed, switch20
- Исключения18
- equals и hashCode15
Разборы подтем
Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.
- Java: equals и hashCode15 вопросов
- Исключения в Java18 вопросов
- Records, sealed и switch в Java20 вопросов
- ООП и полиморфизм в Java22 вопросов
- Типы, обёртки и String в Java25 вопросов
Примеры вопросов с разбором
- Почему при переопределении equals() обязательно переопределять и hashCode()?A)Иначе не скомпилируется: компилятор требует переопределять оба метода строго вместеB)Контракт: равные по equals объекты обязаны иметь равный hashCode — иначе объект теряется в HashMap/HashSetC)HashCode нужен лишь для читаемого вывода объекта в лог, и без его переопределения equals начнёт давать сбои в условиях ifD)Так принято по стилю, но на поведение хеш-коллекций несогласованность этих методов не влияет
показать ответ и разбор
+B)Контракт: равные по equals объекты обязаны иметь равный hashCode — иначе объект теряется в HashMap/HashSet// разбор: Хеш-структуры (HashMap, HashSet) сначала ищут бакет по hashCode, а внутри бакета сверяют equals. Контракт: если a.equals(b), то a.hashCode() == b.hashCode(). Переопределив только equals, вы получите два «равных» объекта с разными хешами — они попадут в разные бакеты, и get/contains не найдёт вставленное. Компилятор это НЕ ловит (оба метода необязательны формально) — баг всплывёт в рантайме. Поэтому методы всегда согласуют, обычно по одному набору полей.
- Чем checked-исключения отличаются от unchecked?A)Checked наследуются от Error, unchecked — от Exception; первые фатальны, вторые обрабатываютсяB)checked (наследники Exception, кроме RuntimeException) компилятор требует обработать или объявить; unchecked — нетC)Checked можно поймать в catch, а unchecked поймать не получится — они сразу завершают программуD)Различие чисто условное и целиком зависит от настроек компилятора: одно и то же исключение можно объявить и checked, и unchecked
показать ответ и разбор
+B)checked (наследники Exception, кроме RuntimeException) компилятор требует обработать или объявить; unchecked — нет// разбор: checked-исключения — наследники Exception, НЕ входящие в ветку RuntimeException (IOException, SQLException). Компилятор заставляет их либо обработать (try/catch), либо объявить в throws — это про ожидаемые внешние сбои. unchecked — RuntimeException и его наследники (NPE, IllegalArgumentException) плюс Error; их объявлять/ловить не обязывают — это, как правило, ошибки в коде. Оба ловятся в catch. Деление задаётся положением в иерархии, а не настройками.
- Что такое record (Java 16+)?A)Неизменяемый носитель данных: компилятор сам генерит конструктор, геттеры, equals, hashCode, toStringB)Аннотация, которая логирует все обращения к полям класса для отладки в рантаймеC)Специальный изменяемый класс с автоматически сгенерированными сеттерами, предназначенный для быстрого прототипирования DTO-объектовD)Тип для хранения строк фиксированной длины наподобие структуры в языке C, без методов
показать ответ и разбор
+A)Неизменяемый носитель данных: компилятор сам генерит конструктор, геттеры, equals, hashCode, toString// разбор: record — компактный способ объявить неизменяемый класс-носитель данных. Из списка компонентов (record Point(int x, int y)) компилятор сам генерирует приватные final-поля, канонический конструктор, accessor-методы (x(), y()), а также equals/hashCode/toString по всем компонентам. Record неявно final и не может наследоваться. Идеален для DTO, ключей, value-объектов. Значения неизменяемы — сеттеров нет; логику валидации кладут в компактный конструктор.
- Что такое инкапсуляция в ООП?A)Сокрытие внутреннего состояния объекта за интерфейсом — доступ к полям только через методыB)Возможность класса-наследника получить и переиспользовать поля и методы своего родителяC)Способность вызвать один и тот же метод у объектов разных классов и получить разное поведениеD)Разбиение большой программы на независимые функции, которые вызывают друг друга по цепочке
показать ответ и разбор
+A)Сокрытие внутреннего состояния объекта за интерфейсом — доступ к полям только через методы// разбор: Инкапсуляция — объединение данных и работающего с ними кода в одном объекте плюс сокрытие деталей: поля делают private, а наружу отдают методы (интерфейс). Так объект сам следит за своими инвариантами — снаружи нельзя привести его в противоречивое состояние в обход проверок. Это упрощает изменение реализации: пока контракт методов держится, внутреннее устройство можно менять. B — это наследование, C — полиморфизм, D — процедурная декомпозиция.
- Чем примитивный тип (int) отличается от ссылочного (Integer)?A)Примитив хранит само значение; ссылочный — ссылку на объект в куче, а значение внутри объектаB)Примитивы хранятся в куче, а ссылочные типы — в стеке, поэтому ссылочные работают быстрееC)Примитив может быть null, а объект-обёртка хранит непосредственно число без ссылки на кучуD)Разница лишь в написании с большой буквы; в рантайме int и Integer оказываются буквально одним и тем же типом данных
показать ответ и разбор
+A)Примитив хранит само значение; ссылочный — ссылку на объект в куче, а значение внутри объекта// разбор: Примитив (int, long, boolean…) хранит непосредственно значение — в стеке для локальных переменных или прямо в поле объекта; у него нет методов и он не может быть null. Обёртка (Integer, Long…) — полноценный объект в куче, переменная держит ссылку на него; обёртка может быть null и нужна там, где требуется объект (дженерики, коллекции). За удобство обёртки платят памятью и разыменованием. Autoboxing автоматически конвертирует между ними.
- Что делает метод hashCode()?A)Возвращает int для раскладки объектов по бакетам хеш-структур; это не уникальный идентификаторB)Возвращает уникальный номер объекта, по которому его можно однозначно найти в памятиC)Сравнивает два объекта и возвращает true/false, заменяя собой метод equals в коллекцияхD)Шифрует внутреннее состояние объекта в строку фиксированной длины для последующего быстрого сравнения и хранения на диске
показать ответ и разбор
+A)Возвращает int для раскладки объектов по бакетам хеш-структур; это не уникальный идентификатор// разбор: hashCode возвращает целое число, по которому хеш-коллекции быстро выбирают бакет для объекта. Это НЕ уникальный id: разные объекты могут иметь одинаковый хеш (коллизия) — это нормально, тогда внутри бакета их различают через equals. Требования контракта: стабильность в пределах жизни объекта (пока не меняются значимые поля) и равные хеши у equals-равных объектов. Хороший hashCode равномерно распределяет объекты, снижая коллизии.
- В чём разница между Error и Exception?A)Error — сбои окружения/JVM (OutOfMemory, StackOverflow), их обычно не ловят; Exception — прикладные, обрабатываютB)Error возникает на компиляции, а Exception — в рантайме; поэтому Error серьёзнееC)Error — это устаревшее название Exception из ранних версий Java, сейчас между ними нет разницыD)Exception не получится перехватить в блоке catch, а Error перехватить можно, поэтому именно Error и применяют для восстановления после сбоя
показать ответ и разбор
+A)Error — сбои окружения/JVM (OutOfMemory, StackOverflow), их обычно не ловят; Exception — прикладные, обрабатывают// разбор: Оба наследуются от Throwable. Error сигнализирует о тяжёлых проблемах среды выполнения, из которых приложению обычно не восстановиться: OutOfMemoryError, StackOverflowError, NoClassDefFoundError — их не принято ловить и «чинить». Exception — про прикладные ситуации, которые код может и должен обрабатывать (файла нет, неверный ввод). Технически поймать можно и Error, но это почти всегда бессмысленно. Оба — рантайм-сущности, к этапу компиляции отношения не имеют.
- Можно ли в record добавить изменяемое поле экземпляра или сеттер?A)Да, record — обычный класс: добавляйте поля и сеттеры так же, как в POJOB)Нет отдельных изменяемых полей экземпляра — компоненты final; но методы и валидацию в компакт-конструкторе добавить можноC)Да, но только через рефлексию в рантайме, иначе компилятор не позволит объявить полеD)Нет, record не позволяет добавлять в него ничего сверх компонентов: ни методов, ни статических полей, ни дополнительных конструкторов
показать ответ и разбор
+B)Нет отдельных изменяемых полей экземпляра — компоненты final; но методы и валидацию в компакт-конструкторе добавить можно// разбор: record спроектирован как неизменяемый носитель: нельзя объявлять дополнительные изменяемые поля ЭКЗЕМПЛЯРА, компоненты хранятся в final-полях, сеттеров нет. Но record — не «запертый» тип: в нём можно объявлять методы (в т.ч. переопределять accessor'ы), статические поля и методы, реализовывать интерфейсы, а в компактном конструкторе — валидировать/нормализовать аргументы. Так сохраняется неизменяемость данных при гибкости поведения. Мутабельность экземпляра — вне модели record.
- Как в Java проявляется полиморфизм подтипов (динамический)?A)Компилятор выбирает перегруженный метод по числу и типам переданных аргументов на этапе сборкиB)Один класс может реализовать сразу несколько интерфейсов и хранить поля каждого из нихC)Объект можно привести к типу-наследнику явным кастом без проверокD)Реальный метод выбирается в рантайме по фактическому классу объекта, а не по типу ссылки
показать ответ и разбор
+D)Реальный метод выбирается в рантайме по фактическому классу объекта, а не по типу ссылки// разбор: Полиморфизм подтипов: ссылка типа-родителя может указывать на объект-потомок, и при вызове переопределённого метода выбирается версия по ФАКТИЧЕСКОМУ классу объекта, а не по типу ссылки (late/dynamic binding). Это позволяет писать код против абстракции и подставлять любую реализацию. A описывает перегрузку (overload) — она разрешается статически по сигнатуре, это не полиморфизм подтипов. Динамическая диспетчеризация — основа паттернов «стратегия», DI и т.п.
это 9 из 100
Ещё 91 вопросов по теме — в тренажёре, с движком повторения
Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.
Частые вопросы
Зачем спрашивают про equals и hashCode?
Потому что нарушение контракта ломает работу коллекций: объект теряется в HashMap или дублируется в Set. Это короткий вопрос, за которым тянется понимание всей библиотеки коллекций.
Что спрашивают про современные возможности Java?
Records и sealed-классы, switch с сопоставлением образцов, var, текстовые блоки. Достаточно понимать, какую проблему каждая возможность решает и где она уместна.