Мок-собеседование по Java: Core и Spring
Голосовое мок-собеседование для Java-разработчиков, которые готовятся к собеседованию Java junior, middle или senior. ИИ-интервьюер задает вопросы на собеседовании Java, как в реальных командах: от equals/hashCode и коллекций до virtual threads, garbage collector, Spring Boot и Hibernate, а затем оценивает каждый ответ по технической точности, полноте и ясности. Выберите Java как технологию или загрузите резюме либо описание вакансии, чтобы получить вопросы под конкретную роль.
Что проверяет собеседование по Java
ООП и Java Core
Инкапсуляция, наследование и полиморфизм, интерфейсы против абстрактных классов, контракт equals/hashCode, неизменяемость String, records, sealed-классы и pattern matching в switch (Java 21).
Коллекции изнутри
Как устроены HashMap, ArrayList и LinkedList, сложность основных операций, ConcurrentHashMap, TreeMap и Sequenced Collections из Java 21. Ожидайте уточнений про коллизии и resize.
Многопоточность и virtual threads
synchronized, volatile и Java Memory Model, атомарные классы, ExecutorService и CompletableFuture, virtual threads из Java 21 и scoped values, ставшие финальными в Java 25.
Память JVM и garbage collector
Heap, stack и Metaspace, поколения объектов, G1 как GC по умолчанию, когда выбирать ZGC, и как искать утечку памяти через heap dump, GC-логи и JFR.
Stream API и функциональный стиль
Промежуточные и терминальные операции, ленивость стримов, Collectors, Optional, функциональные интерфейсы и лямбды, а также когда parallel stream вредит, а не помогает.
Spring Boot и DI
IoC-контейнер, внедрение зависимостей через конструктор, scope бинов, автоконфигурация, профили и @ConfigurationProperties, прокси и @Transactional в Spring Boot 3.x и 4.
JPA и Hibernate
Жизненный цикл сущностей и persistence context, lazy и eager загрузка, проблема N+1, оптимистическая блокировка через @Version и границы транзакций.
Тестирование
JUnit 5 и Mockito, разница между @SpringBootTest и тестовыми срезами вроде @WebMvcTest или @DataJpaTest, интеграционные тесты с Testcontainers.
Вопросы на собеседовании Java по уровням
Junior
Что такое контракт equals и hashCode и что будет, если переопределить только equals?
Что должно быть в сильном ответе:Равные по equals объекты обязаны иметь одинаковый hashCode, а hashCode должен быть стабильным, пока участвующие в сравнении поля не меняются. HashMap и HashSet сначала ищут корзину по hashCode, поэтому без переопределенного hashCode «равный» объект попадет в другую корзину и не найдется. Стоит упомянуть, что records генерируют оба метода автоматически.
Чем ArrayList отличается от LinkedList и что вы выберете по умолчанию?
Что должно быть в сильном ответе:ArrayList хранит элементы в массиве: доступ по индексу O(1), добавление в конец амортизированно O(1), вставка в середину O(n) из-за сдвига. LinkedList — двусвязный список: доступ по индексу O(n) и плохая локальность в кэше процессора. На практике почти всегда ArrayList, а для очереди или стека — ArrayDeque.
В чем разница между checked и unchecked исключениями?
Что должно быть в сильном ответе:Checked-исключения (наследники Exception, но не RuntimeException), например IOException, компилятор заставляет обработать или объявить в throws. Unchecked — наследники RuntimeException, обычно это ошибки программиста: NullPointerException, IllegalArgumentException. Хорошо упомянуть try-with-resources для AutoCloseable и то, что Spring оборачивает ошибки доступа к данным в unchecked-исключения.
Почему String в Java неизменяемый и зачем нужен StringBuilder?
Что должно быть в сильном ответе:Неизменяемость дает потокобезопасность, позволяет кэшировать hashCode и использовать пул строк, а также защищает строки-ключи и параметры от подмены. Каждое «изменение» создает новый объект, поэтому конкатенация в цикле порождает массу временных строк. Для этого берут StringBuilder, который меняет внутренний буфер.
Что такое внедрение зависимостей в Spring и почему советуют инъекцию через конструктор?
Что должно быть в сильном ответе:Spring-контейнер сам создает бины и передает им зависимости, так что класс не создает их через new. Инъекция через конструктор делает зависимости явными, позволяет final-поля и тестирование без Spring, а при единственном конструкторе @Autowired не нужен. Инъекция в поле прячет зависимости и усложняет юнит-тесты.
Middle
Как работает HashMap внутри?
Что должно быть в сильном ответе:HashMap — массив корзин: hashCode ключа перемешивается, а индекс считается как hash & (n - 1). Коллизии хранятся в связном списке, который превращается в красно-черное дерево, когда в корзине 8+ элементов и в таблице минимум 64 ячейки. Когда размер превышает capacity × 0.75, таблица удваивается. Сильный ответ упоминает, что ключ, измененный после вставки, «теряется», а сам HashMap не потокобезопасен.
Чем volatile отличается от synchronized?
Что должно быть в сильном ответе:volatile гарантирует видимость изменений между потоками и упорядоченность через happens-before, но не атомарность: count++ на volatile-поле все равно гонка. synchronized дает и взаимное исключение, и видимость для всего блока. Для счетчиков лучше AtomicInteger или LongAdder, для сложных сценариев — ReentrantLock.
Что такое промежуточные и терминальные операции в Stream API?
Что должно быть в сильном ответе:Промежуточные операции (map, filter, sorted) возвращают новый стрим и ничего не выполняют, пока не вызвана терминальная (collect, reduce, forEach). Стримы ленивые и одноразовые, а операции вроде findFirst или anyMatch могут завершить обход досрочно. Стоит упомянуть, что побочные эффекты в лямбдах — плохая практика, а parallel stream использует общий ForkJoinPool и не подходит для блокирующего I/O.
Почему @Transactional не срабатывает при вызове метода из того же класса?
Что должно быть в сильном ответе:Spring реализует @Transactional через прокси, а вызов this.method() идет мимо прокси, поэтому транзакция не открывается. Решение: вынести метод в отдельный бин или использовать TransactionTemplate. Хорошо добавить, что по умолчанию откат происходит только на unchecked-исключениях и Error, а не на checked.
Что такое проблема N+1 в Hibernate и как ее исправить?
Что должно быть в сильном ответе:Один запрос загружает список сущностей, а затем каждая lazy-ассоциация подгружается отдельным запросом — итого N+1. Обнаруживают через логирование SQL или статистику Hibernate. Исправляют JOIN FETCH, @EntityGraph, batch fetching (@BatchSize или hibernate.default_batch_fetch_size) либо DTO-проекциями; с fetch join коллекций и пагинацией нужна осторожность, потому что Hibernate может пагинировать в памяти.
Senior
Когда virtual threads дают выигрыш, а когда нет?
Что должно быть в сильном ответе:Virtual threads — легкие потоки, которые JVM монтирует на небольшой пул carrier-потоков, так что блокирующий I/O не занимает поток ОС. Они выигрывают в сервисах с большим числом одновременных запросов, ждущих сеть или БД, но не ускоряют CPU-bound задачи. Их не пулят, а нагрузку на ресурсы ограничивают через Semaphore; pinning на synchronized убрали в Java 24, но нативные вызовы по-прежнему пинят. В Spring Boot 3.2+ их включает spring.threads.virtual.enabled=true.
Как выбрать garbage collector и как искать утечку памяти в продакшене?
Что должно быть в сильном ответе:G1 — сбалансированный GC по умолчанию с целевой паузой; ZGC (с Java 23 генерационный по умолчанию) дает паузы меньше миллисекунды на больших хипах ценой дополнительного CPU и памяти; Parallel GC подходит для батчей, где важна пропускная способность. Для утечки смотрят GC-логи (-Xlog:gc*) и JFR, снимают heap dump через jcmd GC.heap_dump и анализируют dominator tree в Eclipse MAT. Типичные виновники — статические кэши без ограничений, ThreadLocal и незакрытые ресурсы.
Как ConcurrentHashMap обеспечивает потокобезопасность и чем он лучше Collections.synchronizedMap?
Что должно быть в сильном ответе:synchronizedMap блокирует всю мапу на каждую операцию, а итерацию нужно синхронизировать вручную. ConcurrentHashMap с Java 8 читает без блокировок, вставляет в пустую корзину через CAS, а при коллизии блокирует только первый узел корзины. compute и merge атомарны для одного ключа, итераторы слабо консистентны, а null-ключи и значения запрещены, потому что null в get был бы неоднозначным.
Как вы проектируете границы транзакций и выбираете между оптимистической и пессимистической блокировкой?
Что должно быть в сильном ответе:Транзакции должны быть короткими: без HTTP-вызовов и тяжелых вычислений внутри, потому что они держат соединение и блокировки. Оптимистическая блокировка через @Version добавляет версию в WHERE при UPDATE и бросает OptimisticLockException, если строку изменили, — хорошо при редких конфликтах вместе с retry. Пессимистическая (@Lock(PESSIMISTIC_WRITE), то есть SELECT ... FOR UPDATE) — когда конфликты частые и повтор дорогой, с риском дедлоков.
Как работает автоконфигурация Spring Boot и как ее отлаживать?
Что должно быть в сильном ответе:@SpringBootApplication включает @EnableAutoConfiguration, а кандидаты перечислены в файле META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (spring.factories для этого в Boot 3 больше не используется). Каждый класс обернут условиями вроде @ConditionalOnClass, @ConditionalOnMissingBean и @ConditionalOnProperty, поэтому собственные бины имеют приоритет. Отлаживают через отчет условий (--debug) или эндпоинт /actuator/conditions.
Как проходит мок-собеседование по Java
- Выберите Java (и другие технологии из своего стека), свой уровень и язык собеседования: украинский, английский или русский. Или загрузите резюме и описание вакансии.
- Отвечайте на каждый вопрос голосом, как на настоящем собеседовании.
- Получите оценку каждого ответа по точности, полноте и понятности и отчёт со слабыми местами.
Как отвечать на вопросы по Java вслух
- →Начинайте с определения в одно предложение, затем механизм, затем короткий пример из проекта. Структуру ответа оценивают не меньше, чем факты.
- →Называйте версию Java, когда это важно: records и sealed-классы (17), virtual threads и Sequenced Collections (21), scoped values (25). Это показывает, что вы не застряли на Java 8.
- →Описывайте код словами, а не диктуйте синтаксис: «сервис получает репозиторий через конструктор и оборачивает сохранение в транзакцию», а не каждую аннотацию и скобку.
- →Говорите о сложности и компромиссах: O(1) против O(n), G1 против ZGC, оптимистическая против пессимистической блокировки. Объяснить, когда решение НЕ подходит, — сильный сигнал.
- →Привязывайте ответы к реальной работе: N+1, найденный в логах SQL, утечка памяти из heap dump, транзакция, которая не откатывалась из-за self-invocation. Конкретика сильнее учебника.
Частые вопросы
Будут ли вопросы про Spring или только Java Core?
И то, и другое. Выберите Spring Boot, Hibernate или другие технологии вместе с Java, и собеседование объединит вопросы по языку и по фреймворкам. Также можно загрузить описание вакансии, чтобы вопросы соответствовали конкретной роли.
Под какую версию Java вопросы?
Вопросы ориентированы на современные LTS-версии Java 21 и 25 и Spring Boot 3.x и 4: virtual threads, records, pattern matching, современные GC. Классические темы вроде коллекций, equals/hashCode и Java Memory Model тоже есть, потому что их до сих пор спрашивают на каждом собеседовании.
Можно пройти собеседование на украинском или английском?
Да. Язык собеседования выбираете вы: украинский, английский или русский. Английский удобен, если вы готовитесь к собеседованию в иностранную компанию, где техническое интервью проходит на английском.
Нужно ли писать код?
Нет. Вопросы устные, вы отвечаете голосом, редактора для live coding нет. Вы объясняете концепции, компромиссы и подход к задаче — как на техническом скрининге. Первое собеседование до 5 вопросов бесплатно, дальше от $1.75 за собеседование без подписки.