сеньорчикОткрыть в Telegram
← все вопросывопросы для собеседований · Java: ядро языка

Вопросы по Java на собеседовании: ядро языка

Ядро языка спрашивают на каждом собесе Java, и обычно с одних и тех же мест: пул строк, контракт equals и hashCode, проверяемые исключения. Эти вопросы выглядят школьными ровно до уточняющего «а почему».

100 вопросов в банке·5 подтем·ниже разбор 9

Из чего состоит тема

Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.

Разборы подтем

Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.

Примеры вопросов с разбором

  1. #equals_hashcode1 / 9
    Почему при переопределении equals() обязательно переопределять и hashCode()?
    A)Иначе не скомпилируется: компилятор требует переопределять оба метода строго вместе
    B)Контракт: равные по equals объекты обязаны иметь равный hashCode — иначе объект теряется в HashMap/HashSet
    C)HashCode нужен лишь для читаемого вывода объекта в лог, и без его переопределения equals начнёт давать сбои в условиях if
    D)Так принято по стилю, но на поведение хеш-коллекций несогласованность этих методов не влияет
    показать ответ и разбор
    +B)Контракт: равные по equals объекты обязаны иметь равный hashCode — иначе объект теряется в HashMap/HashSet

    // разбор: Хеш-структуры (HashMap, HashSet) сначала ищут бакет по hashCode, а внутри бакета сверяют equals. Контракт: если a.equals(b), то a.hashCode() == b.hashCode(). Переопределив только equals, вы получите два «равных» объекта с разными хешами — они попадут в разные бакеты, и get/contains не найдёт вставленное. Компилятор это НЕ ловит (оба метода необязательны формально) — баг всплывёт в рантайме. Поэтому методы всегда согласуют, обычно по одному набору полей.

  2. #exceptions2 / 9
    Чем 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. Деление задаётся положением в иерархии, а не настройками.

  3. #modern_features3 / 9
    Что такое record (Java 16+)?
    A)Неизменяемый носитель данных: компилятор сам генерит конструктор, геттеры, equals, hashCode, toString
    B)Аннотация, которая логирует все обращения к полям класса для отладки в рантайме
    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-объектов. Значения неизменяемы — сеттеров нет; логику валидации кладут в компактный конструктор.

  4. #oop_principles4 / 9
    Что такое инкапсуляция в ООП?
    A)Сокрытие внутреннего состояния объекта за интерфейсом — доступ к полям только через методы
    B)Возможность класса-наследника получить и переиспользовать поля и методы своего родителя
    C)Способность вызвать один и тот же метод у объектов разных классов и получить разное поведение
    D)Разбиение большой программы на независимые функции, которые вызывают друг друга по цепочке
    показать ответ и разбор
    +A)Сокрытие внутреннего состояния объекта за интерфейсом — доступ к полям только через методы

    // разбор: Инкапсуляция — объединение данных и работающего с ними кода в одном объекте плюс сокрытие деталей: поля делают private, а наружу отдают методы (интерфейс). Так объект сам следит за своими инвариантами — снаружи нельзя привести его в противоречивое состояние в обход проверок. Это упрощает изменение реализации: пока контракт методов держится, внутреннее устройство можно менять. B — это наследование, C — полиморфизм, D — процедурная декомпозиция.

  5. #types_strings5 / 9
    Чем примитивный тип (int) отличается от ссылочного (Integer)?
    A)Примитив хранит само значение; ссылочный — ссылку на объект в куче, а значение внутри объекта
    B)Примитивы хранятся в куче, а ссылочные типы — в стеке, поэтому ссылочные работают быстрее
    C)Примитив может быть null, а объект-обёртка хранит непосредственно число без ссылки на кучу
    D)Разница лишь в написании с большой буквы; в рантайме int и Integer оказываются буквально одним и тем же типом данных
    показать ответ и разбор
    +A)Примитив хранит само значение; ссылочный — ссылку на объект в куче, а значение внутри объекта

    // разбор: Примитив (int, long, boolean…) хранит непосредственно значение — в стеке для локальных переменных или прямо в поле объекта; у него нет методов и он не может быть null. Обёртка (Integer, Long…) — полноценный объект в куче, переменная держит ссылку на него; обёртка может быть null и нужна там, где требуется объект (дженерики, коллекции). За удобство обёртки платят памятью и разыменованием. Autoboxing автоматически конвертирует между ними.

  6. #equals_hashcode6 / 9
    Что делает метод hashCode()?
    A)Возвращает int для раскладки объектов по бакетам хеш-структур; это не уникальный идентификатор
    B)Возвращает уникальный номер объекта, по которому его можно однозначно найти в памяти
    C)Сравнивает два объекта и возвращает true/false, заменяя собой метод equals в коллекциях
    D)Шифрует внутреннее состояние объекта в строку фиксированной длины для последующего быстрого сравнения и хранения на диске
    показать ответ и разбор
    +A)Возвращает int для раскладки объектов по бакетам хеш-структур; это не уникальный идентификатор

    // разбор: hashCode возвращает целое число, по которому хеш-коллекции быстро выбирают бакет для объекта. Это НЕ уникальный id: разные объекты могут иметь одинаковый хеш (коллизия) — это нормально, тогда внутри бакета их различают через equals. Требования контракта: стабильность в пределах жизни объекта (пока не меняются значимые поля) и равные хеши у equals-равных объектов. Хороший hashCode равномерно распределяет объекты, снижая коллизии.

  7. #exceptions7 / 9
    В чём разница между 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, но это почти всегда бессмысленно. Оба — рантайм-сущности, к этапу компиляции отношения не имеют.

  8. #modern_features8 / 9
    Можно ли в record добавить изменяемое поле экземпляра или сеттер?
    A)Да, record — обычный класс: добавляйте поля и сеттеры так же, как в POJO
    B)Нет отдельных изменяемых полей экземпляра — компоненты final; но методы и валидацию в компакт-конструкторе добавить можно
    C)Да, но только через рефлексию в рантайме, иначе компилятор не позволит объявить поле
    D)Нет, record не позволяет добавлять в него ничего сверх компонентов: ни методов, ни статических полей, ни дополнительных конструкторов
    показать ответ и разбор
    +B)Нет отдельных изменяемых полей экземпляра — компоненты final; но методы и валидацию в компакт-конструкторе добавить можно

    // разбор: record спроектирован как неизменяемый носитель: нельзя объявлять дополнительные изменяемые поля ЭКЗЕМПЛЯРА, компоненты хранятся в final-полях, сеттеров нет. Но record — не «запертый» тип: в нём можно объявлять методы (в т.ч. переопределять accessor'ы), статические поля и методы, реализовывать интерфейсы, а в компактном конструкторе — валидировать/нормализовать аргументы. Так сохраняется неизменяемость данных при гибкости поведения. Мутабельность экземпляра — вне модели record.

  9. #oop_principles9 / 9
    Как в Java проявляется полиморфизм подтипов (динамический)?
    A)Компилятор выбирает перегруженный метод по числу и типам переданных аргументов на этапе сборки
    B)Один класс может реализовать сразу несколько интерфейсов и хранить поля каждого из них
    C)Объект можно привести к типу-наследнику явным кастом без проверок
    D)Реальный метод выбирается в рантайме по фактическому классу объекта, а не по типу ссылки
    показать ответ и разбор
    +D)Реальный метод выбирается в рантайме по фактическому классу объекта, а не по типу ссылки

    // разбор: Полиморфизм подтипов: ссылка типа-родителя может указывать на объект-потомок, и при вызове переопределённого метода выбирается версия по ФАКТИЧЕСКОМУ классу объекта, а не по типу ссылки (late/dynamic binding). Это позволяет писать код против абстракции и подставлять любую реализацию. A описывает перегрузку (overload) — она разрешается статически по сигнатуре, это не полиморфизм подтипов. Динамическая диспетчеризация — основа паттернов «стратегия», DI и т.п.

это 9 из 100

Ещё 91 вопросов по теме — в тренажёре, с движком повторения

Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.

Частые вопросы