P
prepair.app
Пройти интервью →
EnglishУкраїнськаРусскийDeutsch

Middle Java BackendВопросы на собеседовании Java разработчика

Middle · 2–4 года опыта

Собеседование Java-разработчика охватывает семантику языка, коллекции, многопоточность, Spring и умение рассуждать о JVM. Ниже — вопросы, которые задают чаще всего, каждый с эталонным ответом. Middle: более глубокое понимание, оптимизацию и реальные рабочие ситуации.

Попробовать — без регистрации
Готовим вопрос…

Темы для подготовки

Core Java и ООП
Collections Framework
Многопоточность
Spring Boot и Spring Data
JVM, GC и память
SQL и Hibernate

9 вопросов уровня Middle с ответами

1

Как устроен HashMap внутри и что изменилось в Java 8?

Ответ

Записи лежат в массиве бакетов, индекс берётся из функции хеша ключа; коллизии складываются в связный список внутри бакета. В Java 8 появилась treeification: как только в бакете больше восьми записей, он превращается в красно-чёрное дерево, и худший случай поиска стал O(log n) вместо O(n). Плюс хеш размешивается через h ^ (h >>> 16), чтобы старшие биты влияли на младший индекс.

2

Что гарантирует volatile, а что нет?

Ответ

Гарантирует видимость и упорядочивание: запись сразу публикуется другим потокам, а чтения не кешируются в регистре. Не гарантирует атомарность, поэтому volatile-счётчик всё равно теряет инкременты — ++ это чтение-изменение-запись, и два потока могут прочитать одно значение. volatile берут для флага, который читают многие, а AtomicInteger или synchronized — когда операция объединяет чтение и запись.

3

Объясните propagation у @Transactional. Когда нужен REQUIRES_NEW?

Ответ

Propagation решает, что происходит при вызове транзакционного метода изнутри другой транзакции. REQUIRED по умолчанию присоединяется к существующей, поэтому откат в любом месте откатывает всё. REQUIRES_NEW приостанавливает внешнюю и открывает свою — это нужно для аудит-лога или уведомления, которое должно пережить падение вызывающего кода. Классический баг — ожидать от REQUIRED изоляции сбоя, которой у него нет.

4

В эндпоинте на Hibernate видна проблема N+1. Как найти и починить?

Ответ

Находится включением логирования SQL и подсчётом запросов на один вызов — признак один select и следом сотни почти одинаковых. Возникает, когда загрузили родителей и обращаетесь к ленивой коллекции у каждого. Лечится JOIN FETCH в JPQL, entity graph, @BatchSize для загрузки пачками или проекцией, которая выбирает только нужные ответу поля. Перевод в EAGER это не лечение, а перенос проблемы.

5

Чем Stream отличается от цикла for и когда цикл лучше?

Ответ

Stream описывает конвейер ленивых операций, запускаемый терминальной, и держит фильтрацию с преобразованием читаемыми. Цикл лучше в горячем участке, где абстракция стоит измеримого времени, в логике с побочными эффектами и там, где break посреди выразительнее, чем takeWhile. Настоящая ловушка — параллельные стримы: они помогают только на большом объёме вычислительной работы и обычно вредят в остальных случаях.

6

Сервис тормозит, а CPU низкий. Куда смотреть?

Ответ

Низкий CPU при плохой пропускной способности означает ожидание, а не вычисление: блокирующий ввод-вывод, исчерпанный пул соединений, конкуренция за блокировки или внешний вызов без таймаута. Снимите thread dump и посмотрите, на чём реально стоят потоки. Чаще всего виноват исчерпанный пул соединений, и обычно это следствие транзакции, открытой на время сетевого вызова.

7

Чем автоконфигурация Spring Boot отличается от обычного @Configuration?

Ответ

Автоконфигурация — это условная конфигурация, поставляемая стартером: классы с @ConditionalOnClass или @ConditionalOnMissingBean, которые применяются, только если зависимость есть в classpath и вы сами бин не объявили. Последнее и делает её одновременно волшебной и предсказуемой: ваш бин всегда побеждает, и именно так переопределяется любой дефолт.

8

Чем различаются `wait()`, `sleep()` и `join()`?

Ответ

sleep приостанавливает текущий поток и удерживает захваченную блокировку — так и получают дедлок с невинным на вид кодом. wait освобождает монитор и паркует поток до notify, и именно поэтому вызывать его можно только внутри synchronized. join ждёт завершения другого потока. wait и notify принадлежат Object, а не Thread, потому что блокировка принадлежит объекту.

9

Что делает `transient` и где кусается сериализация?

Ответ

transient исключает поле из сериализации, поэтому при десериализации оно возвращается значением по умолчанию. Помечают им всё вычисляемое, всё крупное и всё секретное: паролю или живому соединению в потоке байтов делать нечего. Более широкая ловушка в том, что сериализация замораживает форму класса в формат: измените поля — и старые данные не прочитаются, если не продумали serialVersionUID и совместимость, поэтому большинство команд берут JSON или protobuf.

🦎

Прочитать ответы недостаточно

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

Пройти интервью Middle Java Backend →
Бесплатно · 3 интервью в месяц

Другие уровни — Java Backend

Junior Java BackendSenior Java BackendВсе вопросы Java Backend

Другие специализации

🔍Middle QA Manual🤖Middle QA Automation🐍Middle Python Backend🐘Middle PHP Backend🦫Middle Go Backend🟢Middle Node.js Backend💎Middle Ruby on Rails🟣Middle .NET Backend Developer🔷Middle C++🟨Middle JavaScript