kata academy

30 частых вопросов на собеседовании по Java: примеры с ответами

Краткие шпаргалки для ответов на вопросы техлида и HR-специалиста.

Время чтения: 5 минут
Хочешь кодить как босс?
Заполняй форму и начни свой путь в IT прямо сейчас!
Эта статья поможет тебе подготовиться к первичному интервью с HR-специалистом и к техсобеседованию. Мы разберем популярные общие вопросы и вопросы на знание языка Java, в том числе с кодом. Для тренировки пробуй самостоятельно отвечать на предложенные вопросы, а потом проверяй себя по нашим шпаргалкам.
Вопросы от HR-специалиста
1) Расскажи о себе и своём опыте
В ответе фокусируйся на последнем месте работы или на том, которое наиболее схоже с этой вакансией. Расскажи, чем занималась компания, на каком проекте ты работал и какие задачи решал. Не вдавайся в детали и не пытайся рассказать все, HR-специалист сам задаст уточняющие вопросы, если это будет необходимо.
2) Почему решил сменить компанию?
Можно говорить о желании финансового роста и пересмотре условий сотрудничества. Нельзя — о конфликте с руководством, командой, в целом, негативно отзываться о предыдущем работодателе. Никто не захочет, чтобы их компания стала следующей, о которой ты будешь рассказывать в негативном ключе.
3) Что для тебя важно на будущем месте работы?
Отметь команду, интересные проекты, профессиональный рост. Не нужно в деталях описывать желаемые условиях работы, это снижает шанс на второй этап интервью в этой компании.
IT-калькулятор зарплат
Узнай свою рыночную зарплату за 1 минуту!
4) Как развиваешься как профессионал? Что читаешь? Слушаешь по теме?
Назови книги, подкасты, тематические блоги и так далее. Важно показать, что у тебя есть мотивация, желание учиться и развиваться в профессии.
5) Кем видишь себя через год/несколько лет?
Ответ должен показать твоё стремление к профессиональному росту, но при этом быть реалистичным. Можно сказать о планах стать ведущим разработчиком и самостоятельно вести сложные модули. Или поделиться желанием развивать навыки менторства и в будущем стать тим-лидом, наставником начинающих специалистов.
6) Расскажи о своих слабых сторонах?
Нельзя называть слабости, которые противоречат требованиям компании или характеризуют тебя как плохого специалиста. Пример ответа: иногда закапываюсь в оптимизацию кода, это замедляет выполнение задачи. В любом случае соблюдаю дедлайны и стараюсь сначала добиться рабочего решения, а потом улучшать его, если есть время.
7) Какими достижениями в работе гордишься?
Для ответа используй схему: ситуация → задача → действие → результат. Фокусируйся на пользе, которую, ты принес проекту.
Вопросы по Java-разработке
1) Что такое ООП? Назови принципы
ООП (объектно-ориентированное программирование) — парадигма, основанная на объектах, объединяющих состояние и методы. Основные принципы: инкапсуляция (скрытие данных и управление доступом), наследование (повторное использование и расширение кода), полиморфизм (один интерфейс — разные реализации) и абстракция (выделение значимых свойств и поведения). Эти принципы делают код гибким, масштабируемым и удобным для моделирования реального мира.
2) Чем отличаются интерфейс и абстрактный класс?
Интерфейс — контракт без состояния, задаёт только методы (с Java 8 могут быть default и static с реализацией), все поля — public static final, класс может реализовать несколько интерфейсов. Абстрактный класс может содержать методы с реализацией и абстрактные методы, поля, конструкторы и состояние, но нельзя создать его экземпляр; класс может наследовать только один абстрактный класс.

Разница: интерфейс описывает поведение («что делать») и полезен для полиморфизма и слабой связности, абстрактный класс задаёт поведение и часть реализации/состояния («как хранить») и удобен, когда нужна общая логика или данные для всех подклассов.
3) Как написать свой immutable-класс, что делать с полями коллекций?
Immutable-класс — это класс, объекты которого после создания нельзя изменить. Для создания объявляем класс final, все поля — private final, без сеттеров, инициализируем всё в конструкторе (делаем глубокие копии изменяемых объектов), возвращаем из геттеров копии или unmodifiable-обёртки. Для вложенных объектов — глубокая копия или неизменяемые типы. В Java 16+ проще использовать record, а для коллекций — List.copyOf, Set.copyOf или Collections.unmodifiable*.
4) Что такое equals() и hashCode()? Контракт, зачем переопределять вместе
equals() проверяет логическое равенство объектов (по умолчанию сравнивает ссылки), а hashCode() возвращает целое число для быстрого поиска в хэш-структурах (HashMap, HashSet).

Контракт: если a.equals(b), то a.hashCode() должен быть равен b.hashCode(). При переопределении одного из методов всегда нужно переопределять и второй, иначе хэш-таблицы могут работать некорректно.

Коллизии (разные объекты с одинаковым hashCode) допустимы, но их количество следует минимизировать; при коллизиях объекты сравниваются через equals(). По умолчанию Object.equals() = ==, Object.hashCode() основан на адресе, а стандартные классы вроде String переопределяют методы для сравнения по содержимому и хэширования по полям.
Курс по Java-разработке с гарантией трудоустройства
Ты можешь выйти на профессиональный уровень разработки всего за 9 месяцев. На такой срок рассчитана программа обучения в Kata Academy, включая подготовку к собеседованиям и поиск работы.

Главное про обучение в Kata Academy
  • Гарантия трудоустройства прописана в договоре
  • Возможность внести основную часть оплаты за обучение уже после выхода на работу
  • Поддержка ментора: задания с обратной связью, ревью, созвоны 1to1 и в группе
  • Подготовка к собеседованиям с HR-консультантом, сопровождение до оффера
Узнай подробнее про курс на сайте.
5) Что такое Generics? Основные концепции и применение на практике
Generics (Java) — механизм (с Java 5) для параметризации классов, интерфейсов и методов типами (например, class Box<T>, List<String>, static <T> T first(List<T>)), цель — типобезопасность на этапе компиляции и избавление от кастов.

Ключевые элементы: параметр типа <T>, bounds (<T extends Number> — ограничение сверху), wildcards (<?>, <? extends T> — для чтения/producer, <? super T> — для записи/consumer; правило PECS — Producer Extends, Consumer Super), алмазный оператор <> (Java 7 — вывод типа при создании), сырые типы (List без параметра) — устарело и небезопасно, и type erasure — стирание параметров типов в байткоде (из-за этого нельзя различать List<String> и List<Integer> во время выполнения, нельзя создавать массивы обобщённых типов, ограничены операции с instanceof и перегрузкой по параметрам типа).

Практика: коллекции (List<T>, Map<K,V>), собственные обобщённые классы/методы (Pair<K,V>, утилиты), API/фреймворки (Optional<T>, Stream<T>, Spring/Hibernate), DAO/Repository (Repository<T>), нужно учитывать ограничения runtime из-за стирания типов при проектировании API.
6) Для чего используют Stream API (промежуточные и термальные операции)?
Stream API (Java 8+) — инструмент для функциональной обработки данных (коллекций, массивов, Optional) через конвейер операций, позволяющий фильтровать, преобразовывать, собирать и агрегировать данные без явных циклов, делая код короче и чище и иногда ускоряя выполнение за счёт внутренних оптимизаций и параллельной обработки.

Промежуточные операции (map, filter, sorted) возвращают новый стрим и формируют конвейер, а терминальные операции (collect, forEach, reduce) запускают выполнение конвейера и возвращают результат или побочный эффект.
7) Напиши код функционального интерфейса с применением лямбда-выражения, поясни его
Пример кода

// Функциональные интерфейсы из java.util.function

Predicate<String> isNotEmpty = s -> s != null && !s.isEmpty();
Function<String, Integer> toLength = String::length; // метод-референс
Consumer<String> printer = System.out::println;
Supplier<Double> rand = () -> Math.random();

// Применение в Stream API

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream()
.map(String::toUpperCase) // Function<String,String>
.filter(isNotEmpty) // Predicate<String>
.forEach(printer); // Consumer<String>

Пояснение: мы передаём поведение (как обрабатывать элементы) в методы map, filter, forEach. Сам метод остаётся универсальным, а конкретные действия задаются через лямбды.
8) Volatile: что даёт, каких гарантий не даёт?
Гарантирует, что запись переменной сразу видна всем потокам и операции до/после обращения выполняются в порядке (happens-before), но не обеспечивает атомарность сложных действий (например, count++). Подходит для безопасного чтения/записи примитивов и ссылок, но для инкрементов или сложных состояний нужна дополнительная синхронизация.
9) Чем отличается map от flatMap? Приведи пример
map и flatMap — промежуточные операции Stream API для преобразования элементов. map применяет функцию T → R к каждому элементу и возвращает один результат на элемент, формируя новый стрим. flatMap применяет функцию T → Stream<R>, объединяя все внутренние стримы в один, позволяя каждому входному элементу порождать несколько (0 или более) значений.

Пример кода

// Пример map: простое преобразование
List<String> words = List.of("hello", "world");
List<Integer> lengths = words.stream()
.map(String::length)
.collect(Collectors.toList()); // [5, 5]

// Пример flatMap: разворачивание вложенных списков
List<List<String>> listOfLists = List.of(
List.of("a", "b"),
List.of("c", "d")
);
List<String> flat = listOfLists.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList()); // ["a", "b", "c", "d"]

В первом примере map вернуло два числа (по одному на каждую строку). Во втором flatMap превратило стрим из двух списков в один стрим из всех элементов. Таким образом, flatMap «сплющивает» вложенность.
10) Как устроена HashMap (бакеты, коллизии, loadFactor)?
HashMap хранит элементы в массиве бакетов (по умолчанию 16), каждый бакет содержит список или дерево узлов Node<K,V>. Индекс бакета вычисляется как hash(key) & (capacity-1).

Коллизии возникают, когда разные ключи попадают в один бакет, и обрабатываются через связный список или дерево.

Load factor (обычно 0.75) задаёт порог заполнения: при превышении capacity * loadFactor таблица расширяется (capacity удваивается) и пересчитываются индексы, что обеспечивает эффективную работу при росте числа элементов.
11) Deadlock, livelock, race condition, как избежать? Напиши пример кода
Deadlock — потоки навсегда блокируют друг друга, удерживая ресурсы; livelock — потоки непрерывно выполняют действия, но не продвигаются; race condition — несколько потоков изменяют одну переменную без синхронизации, результат непредсказуем.

Как избежать: для deadlock — захватывать замки в одном порядке, использовать tryLock() с тайм-аутом; для livelock — вводить задержки или инерцию, менять алгоритм; для гонок — синхронизировать доступ (synchronized/Lock) или использовать атомарные и неизменяемые объекты (AtomicInteger, AtomicBoolean).

Пример кода

public class DeadlockDemo {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void createDeadlock() {
Thread t1 = new Thread(() -> {
synchronized (lockA) {
try { Thread.sleep(50); } catch (InterruptedException

ignored) {}

synchronized (lockB) {
System.out.println("Thread 1");
}
}
});
Thread t2 = new Thread(() -> {
synchronized (lockB) {
try { Thread.sleep(50); } catch (InterruptedException

ignored) {}

synchronized (lockA) {
System.out.println("Thread 2");
}
}
});
t1.start();
t2.start();
}
}
Пройди курс по Java и получи новую работу всего за 9 месяцев! Мы гарантируем трудоустройство с зарплатой на старте от 120 000 рублей. Более 4500 выпускников уже получили оффер мечты, у тебя тоже получится!
12) Виды индексов SQL, как индекс ускоряет поиск?
Индексы в SQL — структуры для ускорения поиска по таблице. В PostgreSQL по умолчанию используются B-Tree (сбалансированные деревья, поиск за логарифмическое время для =, <, >, BETWEEN), есть Hash-индексы (только для точного совпадения), а в других СУБД — bitmap-индексы для столбцов с малым числом значений. Также существуют специализированные индексы (GiST, GIN, BRIN).

Как ускоряют поиск: индекс позволяет не просматривать всю таблицу, а сразу находить строки через структуру дерева или хэш.

Полезны для WHERE столбец = значение или диапазонов, но не для LIKE '%pattern' без префикса.
13) Расскажи про ACID, свойства транзакций
ACID — требования к транзакционной системе: Atomicity — транзакция выполняется полностью или откатывается; Consistency — база остаётся в согласованном состоянии, ограничения и связи не нарушаются; Isolation — параллельные транзакции не влияют друг на друга, результат эквивалентен последовательному выполнению; Durability — после COMMIT изменения сохраняются навсегда, даже при сбое системы.
14) Что такое проблема N+1, как решать?
Проблема N+1 в Hibernate/JPA возникает, когда при загрузке коллекции сущностей один запрос к основной таблице вызывает N дополнительных запросов для связанных объектов, что сильно снижает производительность (часто при FetchType.LAZY). Решения: использовать fetch join (JOIN FETCH) или EntityGraph, применять аннотации Hibernate — @BatchSize, @Fetch(Subselect) для уменьшения числа запросов. Для обнаружения N+1 полезно смотреть SQL-логи Hibernate: один повторяющийся основной запрос и множество похожих маленьких запросов укажут на проблему.
15) Чем отличаются LAZY и EAGER, какие особенности загрузки?
LAZY vs EAGER в JPA/Hibernate: LAZY (ленивая загрузка) подгружает связанные сущности или коллекции только при первом обращении, экономя ресурсы, но создавая дополнительный запрос при использовании; EAGER (жадная загрузка) загружает связанные данные сразу с основной сущностью (обычно через JOIN), удобно если связь всегда нужна, но может перегружать память. По умолчанию @ManyToOne и @OneToOne — EAGER, а @OneToMany и @ManyToMany — LAZY. Рекомендуется делать коллекции LAZY и использовать EAGER только для обязательных связей или маленьких объектов, а большие коллекции подгружать выборочно через JOIN FETCH.
16) Что такое IoC/DI в Spring?
IoC — Inversion of Control означает, что Spring-контейнер управляет созданием и жизненным циклом объектов (бинов), а DI (Dependency Injection) — способ реализации IoC, когда зависимости автоматически внедряются в объект через конструктор, сеттер или поле. Такой подход снижает связанность компонентов, упрощает тестирование и позволяет легко заменять и повторно использовать код.
17) Чем Spring Boot отличается от Spring, что такое автоконфигурация?
Spring требует ручной конфигурации, сканирования компонентов и настройки сервера, а Spring Boot упрощает запуск приложения, предоставляя встроенный веб-сервер, стартеры и возможность запускать проект как самостоятельный JAR. Автоконфигурация — механизм, который автоматически создаёт и настраивает бины на основе зависимостей и настроек проекта (например, Spring MVC при spring-boot-starter-web или DataSource при spring-boot-starter-data-jpa), учитывая существующие бины через @ConditionalOnMissingBean. Преимущества Boot: минимальная конфигурация, встроенный сервер, набор стартеров и автонастройка компонентов.
18) Как работает @Transactional в Spring, когда начинается и заканчивается транзакция?
@Transactional в Spring — аннотация, которая автоматически открывает транзакцию при входе в метод и завершает её при выходе. Spring создаёт прокси (JDK или CGLIB), которые перехватывают вызов метода, начинают новую транзакцию или присоединяются к существующей (в зависимости от propagation), а после выполнения коммитят изменения при успешном завершении или откатывают при исключении. Аннотация работает как AOP-аспект, обеспечивая выполнение всего кода метода в пределах одной транзакции.

Пример кода

@Service
public class AccountService {
@Autowired private AccountRepository repo;

@Transactional
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
Account a = repo.findById(fromId);
a.debit(amount);
// Если ниже бросить RuntimeException, Spring откатит транзакцию:
// if (someError) throw new RuntimeException("Error");
repo.save(a);
Account b = repo.findById(toId);
b.credit(amount);
repo.save(b);
// При нормальном завершении (без исключений) транзакция будет
закоммичена.
}
}
19) Чем монолит отличается от микросервисов? Какие плюсы и минусы есть у микросервисов?
Монолит — это единое приложение со всей логикой в одном модуле, а микросервисы разделяют систему на независимые сервисы, общающиеся по сети.

Плюсы микросервисов: независимые релизы, изоляция ошибок, гибкое масштабирование, выбор технологий. Минусы: сложнее настройка, тестирование и мониторинг, сетевые задержки и больше инфраструктурных затрат.
20) Расскажи про HTTP-методы: GET и POST, почему чувствительные данные лучше передавать через POST?
GET передаёт данные в URL и используется для получения информации, поэтому параметры видны в адресной строке, логах и истории браузера — нельзя передавать чувствительные данные. POST отправляет данные в теле запроса, скрывая их из URL и позволяя передавать большие объёмы. Для операций, изменяющих состояние или содержащих конфиденциальные данные (логин, оплата), используют POST, а для чтения — GET.
21) Чем Mock отличается от Spy?
Mock — это поддельный объект без реальной логики: все его методы возвращают значения по умолчанию, а поведение задаётся через when(...).thenReturn(...). Spy оборачивает реальный объект и по умолчанию вызывает настоящие методы, если не переопределено явно.

Разница: mock — полностью имитирует объект, spy — частично, сохраняя настоящую логику и позволяя подменять отдельные вызовы.
22) Как устроен жизненный цикл Maven?
Maven — инструмент сборки и управления зависимостями для Java-проектов. Работает по жизненному циклу сборки, где каждая команда запускает цепочку фаз: compile (компиляция кода), test (запуск тестов), package (упаковка в JAR/WAR), install (установка в локальный репозиторий) и deploy (публикация в удалённый репозиторий). Например, команда mvn install автоматически выполняет все предыдущие этапы.
23) В чём разница между Git merge и rebase?
merge объединяет изменения из одной ветки в другую, создавая новый коммит слияния и сохраняя полную историю ветвлений. rebase переписывает историю, перенося коммиты поверх другой ветки, делая её линейной.

Когда использовать: merge — для командной работы и сохранения истории; rebase — для локальной чистки истории перед пушем, чтобы сделать её аккуратной.

Подробный разбор большинства вопросов, которые тебе могут задать на собеседованиях, есть на нашем курсе «Java-разработчик». Мы подсчитали, как часто работодатели на реальных собеседованиях задают те или иные вопросы и собрали не только популярные, но и редкие, чтобы подготовить наших выпускников ко всему. Курс проходит с гарантией трудоустройства. Узнай подробнее на сайте.

Статьи для старта в IT

Истории наших выпускников

Стань тем, кто задаёт тон в IT!
Подпишись на нашу рассылку и первым получай статьи по Java, JavaScript, Golang и QA. Позволь себе быть экспертом!