Вопросы на собеседовании Java middle
Вопросы уровня middle — многопоточность, JVM, коллекции изнутри, Stream API.
- 01Чем checked-исключения отличаются от unchecked?
Checked (наследники Exception, кроме RuntimeException) компилятор требует объявить в throws или обработать. Unchecked (RuntimeException и Error) — нет. Выбор: checked — когда…
Middle - 02Какое правило связывает equals() и hashCode()?
Равные по equals объекты обязаны иметь равный hashCode; обратное не требуется — коллизии нормальны. Иначе HashMap и HashSet ищут в другой корзине и не находят равный объект: до…
Middle - 03Что гарантирует ключевое слово volatile для переменной?
volatile даёт видимость (запись сразу видна другим потокам) и запрет переупорядочивания вокруг обращения, но не атомарность: count++ на volatile-поле всё равно теряет обновления.
Middle - 04Почему String в Java неизменяемый?
Неизменяемость String даёт пул строк (литералы разделяются безопасно), кэш hashCode (строка — идеальный ключ HashMap), потокобезопасность без синхронизации и безопасность…
Middle - 05Чем интерфейс отличается от абстрактного класса и что изменили default-методы?
Интерфейс — контракт: класс может реализовать много интерфейсов, состояния (полей экземпляра) нет. Абстрактный класс — общая база с состоянием, конструктором и частичной…
Middle - 06Чем промежуточные операции Stream отличаются от терминальных?
Промежуточные операции (filter, map, sorted) ленивы и возвращают новый Stream — они только описывают конвейер. Терминальная (collect, forEach, count, findFirst) запускает…
Middle - 07Чем HashMap отличается от Hashtable и ConcurrentHashMap?
HashMap — не потокобезопасна, допускает один null-ключ и null-значения. Hashtable — устаревшая, все методы synchronized, null запрещён. ConcurrentHashMap — потокобезопасная с…
Middle - 08Что происходит в HashMap при коллизии ключей?
Коллизии кладутся в один bucket; HashMap ищет нужный ключ через equals, а длинную цепочку (≥8 при таблице ≥64) превращает в красно-чёрное дерево.
Middle - 09Чем volatile отличается от synchronized?
volatile — видимость и порядок для одной переменной без блокировки. synchronized — видимость плюс взаимное исключение: блок целиком выполняется одним потоком, поэтому составные…
Middle - 10Чем Comparable отличается от Comparator и что значит согласованность порядка с equals?
Comparable — естественный порядок, который задаёт сам класс (compareTo), один. Comparator — внешний порядок, их может быть сколько угодно, комбинируются через…
Middle - 11Какое свойство LinkedHashMap отличает его от HashMap?
LinkedHashMap — HashMap плюс двусвязный список записей: обход в порядке вставки (по умолчанию) или в порядке доступа (accessOrder = true).
Middle - 12Чем IO отличается от NIO?
IO (java.io) — потоки байт и символов, блокирующие: чтение держит поток, модель «поток на соединение». NIO (java.nio) — каналы и буферы, неблокирующий режим и Selector: один поток…
Middle - 13Зачем нужен serialVersionUID?
serialVersionUID — версия класса для встроенной сериализации. При несовпадении версии в потоке и у локального класса — InvalidClassException. Если не объявить, JVM вычислит её из…
Middle - 14Как правильно использовать Optional?
Optional — тип возвращаемого значения «результата может не быть», видимый в сигнатуре. Распаковывают через map, flatMap, filter, orElseGet, orElseThrow, а не isPresent() + get()…
Middle - 15Чем map, flatMap и filter отличаются в Stream API?
map — один элемент → один элемент (преобразование). flatMap — один элемент → поток элементов, все потоки разворачиваются в один. filter — оставляет элементы, удовлетворяющие…
Middle - 16Чем LocalDateTime отличается от ZonedDateTime?
LocalDateTime — дата и время без зоны: «15 марта, 09:00» неизвестно где. ZonedDateTime — с ZoneId и правилами перехода на летнее время: конкретный момент. Instant — момент на…
Middle - 17В чём опасность ThreadLocal в пуле потоков?
Поток в пуле переиспользуется: значение ThreadLocal, не очищенное после задачи, протекает в следующую задачу (чужой пользователь, транзакция) и удерживает память. Правило: try {…
Middle - 18Что такое deadlock и как его предотвращать?
Deadlock — циклическое ожидание: поток A держит замок 1 и ждёт замок 2, поток B держит 2 и ждёт 1. Предотвращают единым порядком захвата, tryLock с таймаутом и откатом, короткими…
Middle - 19Чем различаются CountDownLatch, CyclicBarrier и Semaphore?
CountDownLatch — одноразовое ожидание N событий: дошёл до нуля — открыт навсегда. CyclicBarrier — переиспользуемая точка встречи N потоков между раундами. Semaphore — ограничение…
Middle - 20Что такое class loader и как работает делегирование загрузки классов?
ClassLoader находит байт-код и превращает его в класс. Иерархия: Bootstrap (ядро JDK) → Platform (модули платформы) → Application (classpath). Модель parent-first: запрос сначала…
Middle - 21Какой инструмент обычно используют для корректных Java microbenchmarks?
JMH (Java Microbenchmark Harness) от разработчиков OpenJDK: учитывает прогрев, форки JVM, устранение мёртвого кода, свёртку констант, статистику по итерациям.
Middle - 22Реализуй потокобезопасный счётчик Counter с методами increment() и get().
Проще всего — AtomicInteger: incrementAndGet() и get(), без блокировок. Альтернатива — synchronized на обоих методах (важно: и на чтении тоже, иначе нет видимости).
Middle - 23Почему int v = flag ? map.get(key) : 0 (map.get может вернуть null) способно бросить NPE?
Если одна ветвь тернарного оператора int, а другая Integer, тип всего выражения — int: обёрточная ветвь распаковывается, и null даёт NPE, хотя код выглядит безопасным.
Middle - 24Чем int[] на миллион чисел выгоднее List<Integer> того же размера?
int[] — сплошной блок ~4 МБ. List<Integer> — миллион отдельных объектов Integer (16 байт каждый) плюс массив ссылок: в 4–5 раз больше памяти, нагрузка на GC и промахи кэша при…
Middle - 25Почему стек реализуют через ArrayDeque, а не java.util.Stack?
Стек и очередь в одном потоке — ArrayDeque (кольцевой массив, O(1) по краям, данные подряд). Stack наследует Vector: synchronized на каждой операции и доступ по индексу в середину…
Middle - 26В каком порядке выдаёт элементы итерация (for-each) по PriorityQueue?
Итерация по PriorityQueue не отсортирована: куча гарантирует только «родитель ≤ детей». Отсортированный порядок даёт лишь повторный poll().
Middle - 27Какая алгоритмическая сложность операций PriorityQueue (бинарной кучи)?
offer и poll — O(log n) (просеивание вверх и вниз), peek — O(1) (корень), remove(Object) и contains — O(n) (линейный поиск).
Middle - 28Какое ограничение Future решает CompletableFuture?
Future — дескриптор результата с единственным способом получить значение: блокирующий get(). CompletableFuture позволяет описать цепочку продолжений (thenApply, thenCompose…
Middle - 29Чем thenCompose отличается от thenApply в CompletableFuture?
thenApply — как map: функция значение → значение. thenCompose — как flatMap: функция значение → новый CompletableFuture, результат «разворачивается». Без thenCompose получилось бы…
Middle - 30Каков компромисс трёх базовых алгоритмов GC: mark-sweep, mark-compact, copying?
Mark-sweep — пометить живых, освободить остальное: быстро, но фрагментация. Mark-compact — плюс уплотнение живых: нет фрагментации, но перемещение дорого. Copying — копировать…
Middle - 31Что показывают метрики allocation rate и promotion rate?
Allocation rate — сколько МБ/с приложение создаёт объектов: чем выше, тем чаще minor GC. Promotion rate — сколько МБ/с переезжает в старое поколение: чем выше, тем чаще old/full…
Middle - 32Чем this внутри лямбды отличается от this внутри анонимного класса?
В лямбде this — окружающий объект: она не вводит своей области видимости. В анонимном классе this — сам анонимный объект, и его поля могут перекрывать внешние. Лямбда…
Middle - 33Почему лямбда может захватывать только effectively final локальные переменные?
Лямбда захватывает значение локальной переменной (копию), а не ячейку: локальная переменная живёт в кадре стека и исчезает вместе с методом, а лямбда может жить дольше и…
Middle - 34Чем collect отличается от reduce при сборке стрима?
reduce — неизменяемая свёртка: из двух значений получается новое (сумма, максимум). collect — изменяемая свёртка: элементы накапливаются в один контейнер (список, карта…
Middle - 35Что произойдёт в Collectors.toMap, если два элемента дают одинаковый ключ, а merge-функция не передана?
IllegalStateException: Duplicate key. При возможных дубликатах передают третий аргумент — функцию слияния: (a, b) -> a, сумма, конкатенация.
Middle - 36Как одним коллектором получить «количество элементов в каждой группе»?
groupingBy(classifier, counting()) — downstream-коллектор counting сворачивает каждую группу в число (Long).
Middle - 37Чем switch-выражение (case L -> …) надёжнее старого switch?
Стрелочный case L -> не проваливается и не требует break; switch-выражение возвращает значение (для блока — yield); по enum и sealed-типам компилятор проверяет полноту — забытый…
Middle - 38Чем Instant и LocalDateTime отличаются и когда брать Duration, а когда Period?
Instant — момент на шкале (UTC, от эпохи); LocalDateTime — дата и время без зоны, моментом не является. Duration — машинное время в секундах и наносекундах, Period — календарные…
Middle - 39Что требуется, чтобы класс был ПО-НАСТОЯЩЕМУ неизменяемым?
Рецепт: все поля private final, нет сеттеров и других мутаторов, запрет наследования (final-класс или приватный конструктор с фабриками), защитные копии изменяемых данных на входе…
Middle - 40Конструктор сохранил переданный List по ссылке (this.items = items). Почему объект всё равно изменяем?
Поле хранит чужую ссылку: вызывающий меняет список снаружи, и «неизменяемый» объект меняется. final запрещает переприсвоить поле, но не менять содержимое. Нужна защитная копия на…
Middle - 41Почему про immutable-объект говорят «потокобезопасен без синхронизации»?
Модель памяти гарантирует: если все поля final и this не утёк из конструктора, любой поток, получивший ссылку на готовый объект, увидит поля проинициализированными — без…
Middle - 42Как в immutable-дизайне моделируют «изменение» и снижают его цену?
«Изменение» — новый объект: методы withX возвращают копию с одним изменённым полем. Для частых правок — изменяемый Builder, отдающий неизменяемый результат, или…
Middle - 43Чего record НЕ делает за вас при проектировании неизменяемого носителя данных?
Record делает компоненты private final и генерирует конструктор, аксессоры, equals, hashCode, toString, но не делает защитных копий: изменяемый компонент (List, массив, Date)…
Middle - 44В коде расчёта комиссии есть метод с цепочкой if по типу платежа, и при добавлении каждого нового способа оплаты приходится править этот метод и ещё три похожих. Какой принцип SOLID нарушен в первую очередь?
Open/Closed Principle: новое поведение требует правки существующего кода, а не добавления нового. Растущая цепочка if или switch по типу, повторённая в нескольких местах, …
Middle - 45Что такое Liskov Substitution Principle и что обязан соблюдать подтип?
Подтип должен быть подставим вместо базового типа без сюрпризов для вызывающего: не усиливать предусловия, не ослаблять постусловия, сохранять инварианты, не бросать новых…
Middle - 46Сервис получает через конструктор зависимость типа PostgresOrderRepository (конкретный класс), которую внедряет Spring. Что здесь верно?
DI есть, DIP нарушен: зависимость приходит снаружи (техника внедрения), но сервис зависит от конкретного класса инфраструктуры, а не от абстракции. DIP — принцип: верхний уровень…
Middle - 47Что утверждает Interface Segregation Principle?
Клиенты не должны зависеть от методов, которыми не пользуются: лучше несколько узких интерфейсов под роли, чем один толстый. Толстый интерфейс создаёт ложную связанность, а…
Middle - 48Два метода расчёта скидки — для розницы и для опта — сегодня содержат идентичный код, но правила задают разные владельцы и они уже расходились в прошлом. Что правильнее сделать?
Оставить дублирование: совпал код, но не знание. Правила меняются по разным причинам и разными владельцами — объединение создаст управляющую связанность: первое расхождение даст…
Middle - 49Что верно про YAGNI?
YAGNI — не строить под несуществующие требования. Цена преждевременной фичи: постройка, задержка нужного, сопровождение лишнего кода и исправление, если угадали неверно. На тесты…
Middle - 50Какой из фрагментов нарушает закон Деметры?
Нарушение — путешествие по графу чужих объектов: order.getCustomer().getAddress().getCity().getName() фиксирует в вызывающем коде всю структуру, и любое изменение по пути его…
Middle - 51Что верно про связность (cohesion) и связанность (coupling)?
Связность (cohesion) — насколько элементы модуля служат одной задаче: хотим высокую. Связанность (coupling) — насколько модуль завязан на устройство других: хотим низкую.
Middle - 52Что такое anemic domain model, чем она плоха и когда всё-таки допустима?
Анемичная модель: сущности — мешки геттеров и сеттеров, вся логика в сервисах. Снаружи ООП, внутри процедурный код: инварианты никто не охраняет, одно правило дублируется по…
Middle - 53Чем Integer.valueOf(127) отличается от паттерна Factory Method по GoF?
Factory Method (GoF) построен на наследовании: базовый класс объявляет метод создания, а какой продукт создать — решает подкласс. Integer.valueOf — статическая фабрика (идиома…
Middle - 54Какие преимущества даёт статическая фабрика по сравнению с публичным конструктором?
Три плюса из Effective Java: имя (of, copyOf, ofNullable — различимы, в отличие от конструкторов с одной сигнатурой), не обязана создавать новый объект (кэш, синглтон), может…
Middle - 55Почему паттерн Builder особенно удобен при создании неизменяемых объектов?
У неизменяемого объекта без билдера два плохих варианта: сеттеры (и он уже изменяем) или конструктор с длинным списком однотипных аргументов. Builder собирает состояние по…
Middle - 56Что отличает Abstract Factory от обычной фабрики?
Abstract Factory создаёт семейство связанных объектов, согласованных между собой, так что клиент не смешает объекты разных семейств. Одна фабрика одного продукта — это ещё не…
Middle - 57Чем поверхностное копирование отличается от глубокого и как правильно копировать объекты в современной Java?
Поверхностная копия копирует значения полей — то есть ссылки: вложенный изменяемый список общий у оригинала и копии. Глубокая — копирует весь граф. clone() — неудачный дизайн…
Middle - 58По какому признаку проще всего отличить Adapter от Decorator и Proxy?
По интерфейсу: адаптер меняет интерфейс (InputStreamReader превращает байтовый поток в символьный), декоратор и прокси сохраняют его. Механизм у всех трёх один — композиция и…
Middle - 59Какой паттерн лежит в основе конструкции new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))?
Decorator: каждая обёртка добавляет один аспект (буферизацию, распаковку) и остаётся тем же InputStream. Комбинацию выбирает клиент во время выполнения — без взрыва числа…
Middle - 60Spring оборачивает бины в прокси, чтобы работали @Transactional и @Cacheable. Какие практические следствия из этого вытекают?
Прокси перехватывает только внешние вызовы: this.method() внутри класса идёт мимо прокси — аннотация не сработает. CGLIB не проксирует final-классы и final-методы, JDK-прокси…
Middle - 61Что произойдёт при вызове add на списке, полученном из Arrays.asList(array)?
UnsupportedOperationException: Arrays.asList — адаптер над массивом фиксированного размера. add и remove не поддержаны, а set пишет прямо в массив (и изменения массива видны в…
Middle - 62Какой паттерн реализуют SLF4J и JdbcTemplate по отношению к тому, что они скрывают?
Facade — простой вход в сложную подсистему. SLF4J — Simple Logging Facade for Java. JdbcTemplate скрывает ритуал JDBC: соединение, statement, обработка SQLException, закрытие…
Middle - 63Чем паттерн Proxy отличается от Decorator, если у обоих тот же интерфейс, что и у обёрнутого объекта?
Структурно почти одинаковы, различие — в намерении: декоратор добавляет поведение, и цепочку собирает клиент; прокси управляет доступом к объекту (ленивое создание, права, кэш…
Middle - 64Какой паттерн представляет java.util.Comparator?
Strategy: алгоритм сравнения передаётся снаружи, сортировка при этом не меняется.
Middle - 65В чём принципиальная разница между Template Method и Strategy?
Template Method — наследование на этапе компиляции: скелет алгоритма в базовом классе, подкласс заполняет шаги. Strategy — композиция во время выполнения: алгоритм передаётся…
Middle - 66Что верно про реализацию паттерна Observer в современной Java?
java.util.Observable устарел с Java 9. Современные формы: ApplicationEventPublisher и @EventListener в Spring, реактивные потоки (Flow, Reactor), брокеры сообщений. Подводные…
Middle - 67Какой паттерн реализуют цепочка сервлетных фильтров и фильтр-цепочка Spring Security?
Chain of Responsibility: запрос идёт по звеньям, и каждое решает, обработать ли его и передавать ли дальше (chain.doFilter). Возможность прервать цепочку — отличие от декоратора…
Middle - 68State и Strategy структурно почти одинаковы. Что их различает?
Кто управляет подстановкой: стратегию выбирает клиент снаружи, и она обычно не меняется; состояние объект меняет сам в ответ на события, и переходы — часть его логики.
Middle - 69Поток пытается войти в synchronized-блок, занятый другим потоком. В каком состоянии он находится?
BLOCKED — ожидание входа в занятый монитор synchronized. Шесть состояний: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
Middle - 70Что верно про прерывание потока через interrupt()?
interrupt() — просьба, а не приказ: выставляет флаг; блокирующие sleep, wait, join бросают InterruptedException и сбрасывают флаг. Поток проверяет флаг сам и завершается в…
Middle - 71Что верно про daemon-потоки?
JVM завершается, когда остались только daemon-потоки; они обрываются без выполнения finally. Флаг ставится до start(), иначе IllegalThreadStateException.
Middle - 72Почему фабрики из класса Executors считают опасными в production-коде?
Скрытые неограниченные ресурсы: newFixedThreadPool — неограниченная очередь (задачи копятся до OutOfMemoryError, наружу не идёт никакого отказа), newCachedThreadPool …
Middle - 73Сервис в основном ходит по сети: на каждую задачу примерно 90% времени — ожидание ответа и 10% — вычисления. Как выбрать размер пула потоков?
IO-bound: ядра × (1 + W/C), где W — ожидание, C — вычисления; при 90/10 — около 10 × ядер. CPU-bound — примерно по числу ядер. Это ориентир: реальный предел часто задаёт внешний…
Middle - 74Задача, отправленная в пул через submit(), бросает RuntimeException, но в логах ничего нет. Почему?
submit() прячет исключение в Future: оно появится только при get() в ExecutionException. Если результат никто не запрашивает — ошибка исчезает бесследно. execute() пропускает…
Middle - 75Какие пары действий образуют отношение happens-before?
Happens-before — гарантия, что результаты A видны в B. Пары: порядок внутри потока, unlock → последующий lock того же монитора, запись volatile → последующее чтение того же поля…
Middle - 76Нужно ограничить число одновременных обращений к внешнему API десятью, не ограничивая при этом число рабочих потоков. Какой примитив подходит?
Semaphore с десятью разрешениями: acquire перед вызовом, release в finally. Он ограничивает число одновременных доступов к ресурсу, не трогая число потоков.
Middle - 77Можно ли переиспользовать CountDownLatch после того, как счётчик дошёл до нуля?
Нет: дошедший до нуля CountDownLatch открыт навсегда, метода сброса нет. Для повторяющихся раундов — CyclicBarrier или Phaser; либо новый latch на каждый раунд.
Middle - 78В коде вызывается semaphore.acquire(), затем работа с ресурсом, затем semaphore.release() в конце метода. Что здесь опасно?
release не в finally: исключение навсегда съедает разрешение. С каждым сбоем параллелизм падает на единицу, пока система не встанет без единой записи в логе.
Middle - 79Что верно про практическое применение виртуальных потоков?
Не пулить (поток на задачу), применять для блокирующего ввода-вывода, помнить, что ThreadLocal на миллионах потоков дорог, и ограничивать доступ к внешним ресурсам семафором — пул…
Middle - 80Что происходит с виртуальным потоком, когда он выполняет блокирующий сетевой вызов?
Unmount: стек виртуального потока (continuation) сохраняется в куче, несущий поток освобождается для других задач. Когда данные пришли — mount обратно, возможно на другой несущий…
Middle - 81На какой гипотезе построено разделение кучи на поколения?
Слабая гипотеза о поколениях: почти все объекты умирают молодыми, а пережившие несколько сборок живут долго. Отсюда молодое поколение с копирующим сборщиком: цена сборки…
Middle - 82Зачем в молодом поколении две области Survivor, а не одна?
Копирующему сборщику нужна пустая область назначения: живые из Eden и занятого Survivor копируются в свободный Survivor, после чего Eden и бывший Survivor очищаются целиком, а…
Middle - 83В приложении участились длинные паузы full GC, при этом старое поколение почти всегда заполнено. О чём это говорит?
Живых данных больше, чем помещается. Смотрят на занятость после каждого full GC: ползёт вверх — утечка, держится высоко, но стабильно — кучи мало под рабочий набор. Лечат причину…
Middle - 84Что верно про типы ссылок в Java?
Strong — не собирается, пока достижим. Soft — очищается при нехватке памяти (кэш, который не жалко). Weak — на ближайшей сборке, если нет сильных ссылок (WeakHashMap, метаданные)…
Middle - 85Что относится к GC roots — корням достижимости?
Корни — точки начала обхода: локальные переменные и параметры в стеках живых потоков, статические поля загруженных классов, JNI-ссылки, сами активные потоки и удерживаемые…
Middle - 86Почему finalize() признан неудачным механизмом и что использовать вместо него?
finalize не гарантирует ни вызова, ни времени, замедляет сборку (объект переживает лишний цикл) и может «воскресить» объект. Устарел в Java 9, помечен к удалению в Java 18…
Middle - 87Нужна структура с быстрым поиском по ключу, которая при обходе отдаёт элементы в порядке их добавления. Что выбрать?
LinkedHashMap: поиск по ключу O(1) и обход в порядке добавления.
Middle - 88Что верно про неизменяемые и защитные коллекции?
List.of и List.copyOf — настоящие неизменяемые коллекции, null запрещён. Collections.unmodifiableList — представление: через исходную ссылку список по-прежнему меняется. Объекты…
Middle - 89Почему добавление в конец ArrayList считается амортизированно O(1), хотя иногда требует копирования всего массива?
Ёмкость растёт в 1,5 раза: копирования всё реже, сумма копирований на n вставок — геометрическая прогрессия, то есть O(n). На одну вставку — константа в среднем, хотя отдельная…
Middle - 90Сколько стоит удаление элемента из середины ArrayList и почему?
O(n): хвост сдвигается влево через System.arraycopy, последняя ячейка обнуляется. Удаление в цикле — квадратичная работа.
Middle - 91Что верно про управление ёмкостью ArrayList?
Ёмкость растёт, но не уменьшается сама; clear() обнуляет ссылки, а массив остаётся прежнего размера. Пустой ArrayList без аргументов выделяет массив лениво — при первом добавлении…
Middle - 92Почему утверждение «вставка в середину LinkedList работает за O(1)» вводит в заблуждение?
O(1) — только перецепление ссылок. Чтобы вставить по индексу, сначала нужно дойти до позиции — O(n). Итого add(i, x) линейный и у LinkedList, и у ArrayList.
Middle - 93Почему ArrayList обычно обходит LinkedList даже там, где асимптотика формально в пользу связного списка?
Локальность данных: массив лежит подряд и попадает в кэш процессора блоками, узлы LinkedList разбросаны по куче — промах кэша на каждом шаге. Плюс узел — отдельный объект с…
Middle - 94Нужна очередь FIFO внутри одного потока. Что выбрать по умолчанию?
ArrayDeque: кольцевой массив, offer и poll — O(1), без узла на элемент и промахов кэша.
Middle - 95Как получить LRU-кэш на базе LinkedHashMap?
new LinkedHashMap<>(cap, 0.75f, true) (accessOrder) + переопределённый removeEldestEntry, возвращающий size() > max. Get переносит запись в конец, самая давно неиспользуемая — в…
Middle - 96Какой ценой LinkedHashMap поддерживает предсказуемый порядок обхода по сравнению с HashMap?
Цена — две дополнительные ссылки на запись и поддержка списка при вставке и удалении. get и put остаются O(1); обход даже быстрее — по списку, а не по всем корзинам.
Middle - 97Что произойдёт при обходе LinkedHashMap, созданного с accessOrder = true, если во время итерации вызвать get() по существующему ключу?
В режиме accessOrder даже get переносит запись в конец — это структурная модификация, итератор бросит ConcurrentModificationException.
Middle - 98Как устроен HashSet внутри?
HashSet — это HashMap: элементы — ключи, значение — общий объект-заглушка. LinkedHashSet построен на LinkedHashMap, TreeSet — на TreeMap.
Middle - 99В TreeSet добавили два объекта, для которых equals возвращает false, но компаратор считает их равными. Что произойдёт?
Второй объект не будет добавлен: TreeSet считает элементы равными, если сравнение даёт 0, equals не вызывается.
Middle - 100Объект добавили в HashSet, после чего изменили у него поле, участвующее в hashCode. Что теперь вернёт contains для этого же объекта?
Скорее всего false: объект лежит в корзине по старому хешу, а ищут по новому. При этом в итерации он останется — и удалить его через remove уже не получится.
Middle - 101В цикле for-each по списку вызывается list.remove(element). Что произойдёт?
ConcurrentModificationException — даже в одном потоке: for-each идёт через итератор, а list.remove меняет коллекцию мимо него; итератор сверяет modCount и падает.
Middle - 102Какие способы удалить элементы по условию во время обхода коллекции корректны?
Корректно: removeIf, явный Iterator.remove(), проход по индексам с конца. Удаление в for-each — CME, по индексам вперёд — пропуск элементов.
Middle - 103Чем ListIterator отличается от обычного Iterator?
ListIterator — только для списков: ход в обе стороны (hasPrevious, previous), индексы (nextIndex), изменение на месте — set и add.
Middle - 104Нужно быстро находить ближайшую запись с ключом не больше заданного и выбирать все записи в диапазоне дат. Какая структура подходит?
TreeMap как NavigableMap: floorKey/ceilingKey/lowerKey/higherKey и subMap, headMap, tailMap за O(log n). Хеш-таблица порядок не хранит.
Middle - 105Что произойдёт при попытке положить null-ключ в TreeMap?
NullPointerException: TreeMap сравнивает ключи, а null сравнить естественным порядком нельзя. HashMap допускает один null-ключ.
Middle - 106Какие требования входят в контракт equals?
Рефлексивность (a.equals(a)), симметричность, транзитивность, согласованность (повторные вызовы дают одно и то же) и a.equals(null) == false. Самое частое нарушение …
Middle - 107Метод принимает StringBuilder и внутри выполняет sb.append("x"), а затем sb = new StringBuilder(). Что увидит вызывающий код?
Вызывающий увидит добавленный символ, но не новый объект: Java всегда передаёт по значению, а для ссылочных типов значение — копия ссылки. Мутация объекта по копии видна всем…
Middle - 108У списка есть перегрузки remove(int index) и remove(Object o). Что сделает list.remove(1) для List<Integer>?
Удалит элемент с индексом 1: перегрузка выбирается на компиляции, и remove(int) подходит без упаковки — на первой фазе подбора. Удалить значение 1 …
Middle - 109Что верно про varargs?
Varargs — сахар над массивом: внутри параметр — обычный массив, он единственный и последний, без аргументов приходит пустой массив, а не null. Каждый вызов выделяет массив …
Middle - 110В try-with-resources исключение бросают и тело блока, и метод close(). Какое исключение получит вызывающий код?
Наверх идёт исключение из тела — оно о настоящей причине. Исключение из close() прикрепляется к нему как suppressed (getSuppressed(), видно в стектрейсе). Ручной try/finally терял…
Middle - 111Чем интерфейс AutoCloseable отличается от Closeable?
AutoCloseable (Java 7) — для любых ресурсов, close() бросает Exception. Closeable (java.io, старше) — его наследник под ввод-вывод: close() бросает IOException и обязан быть…
Middle - 112Код открывает соединение, затем в том же try создаёт из него statement, и оба объявлены в скобках try-with-resources. В каком порядке они закроются?
Сначала statement, потом соединение — в обратном порядке объявления, как раскручивается стек: зависимый ресурс закрывается раньше того, из которого получен.
Middle - 113Почему List<String> нельзя присвоить переменной типа List<Object>?
Дженерики инвариантны: если бы List<Object> objs = strings компилировалось, через objs можно было бы положить Integer, а потом получить ClassCastException при чтении из списка…
Middle - 114Что можно делать со списком, объявленным как List<? extends Number>?
Читать как Number можно, добавлять нельзя ничего, кроме null: за ссылкой может быть List<Integer> или List<Double>, и компилятор не знает какой. Симметрично List<? super Integer>…
Middle - 115Метод должен перекладывать элементы из источника в приёмник. Какая сигнатура правильна по правилу PECS?
void copy(List<? super T> dest, List<? extends T> src): источник производит — extends, приёмник потребляет — super. Так объявлен Collections.copy.
Middle - 116Что верно про record в Java?
Компилятор генерирует private final поля, канонический конструктор, аксессоры (name(), без get), equals, hashCode, toString по всем компонентам. Record неявно final, наследует…
Middle - 117Когда record — неудачный выбор?
Record прозрачен: компоненты — публичный контракт. Не подходит для изменяемых сущностей со скрытым представлением и охраняемыми инвариантами, для JPA-сущностей (нужны конструктор…
Middle - 118Что произойдёт, если объявить record с полем-массивом и сравнить два таких объекта с одинаковым содержимым массива?
equals вернёт false: сгенерированный equals сравнивает компоненты их собственным equals, а у массива это сравнение по ссылке. hashCode тоже будет по идентичности, toString…
Middle - 119Какое главное преимущество даёт sealed-иерархия при использовании switch с pattern matching?
Закрытый список наследников делает проверку полноты switch работой компилятора: не нужен default, а новый подтип — ошибка компиляции во всех switch, которые его не обрабатывают…
Middle - 120Что обязан сделать наследник sealed-класса?
Наследник sealed-класса обязан: быть в permits (или в том же файле, если permits опущен), объявить себя final, sealed или non-sealed, лежать в том же модуле (вне модулей — в том…
Middle - 121Что даёт pattern matching в instanceof по сравнению с классической проверкой?
Проверка и приведение объединяются: if (o instanceof String s) сразу даёт переменную s нужного типа. Нет дублирующего приведения, которое может разойтись с проверкой.
Middle - 122Почему встроенную Java-сериализацию считают небезопасной и устаревшей?
Безопасность: десериализация сама создаёт объекты классов из потока и вызывает их методы восстановления до любой проверки — из классов в classpath собирают гаджет-цепочку и…
Middle - 123Что произойдёт с полем, помеченным transient, при сериализации и последующей десериализации?
Поле не попадёт в поток, а после восстановления получит значение по умолчанию для типа (null, 0, false) — инициализатор поля и конструктор не выполняются.
Middle - 124Чем Externalizable отличается от Serializable?
Externalizable — полный ручной контроль: формат пишут writeExternal и readExternal, нужен публичный конструктор без аргументов (вызывается при восстановлении). Serializable …
Middle - 125Что означают позиция, лимит и ёмкость у ByteBuffer, и что делает flip()?
Ёмкость — размер буфера, позиция — курсор следующего чтения или записи, лимит — граница доступных данных. flip() ставит лимит на текущую позицию и обнуляет позицию — переключает…
Middle - 126Как виртуальные потоки изменили типичный выбор между блокирующим IO и неблокирующей моделью на Selector?
Главный довод за event loop — дороговизна потока — снят: виртуальный поток дешёв и при блокировке отцепляется от несущего. Можно писать блокирующий читаемый код при высокой…
Middle - 127Что верно про JIT-компиляцию в HotSpot?
Код сначала интерпретируется, горячие методы компилирует C1 (быстро, с профилированием), затем C2 (агрессивные оптимизации по профилю). Оптимизации спекулятивны: встраивание по…
Middle - 128Почему java.util.Stack, унаследованный от Vector, считают ошибкой дизайна?
«Стек — это вектор» неверно: наследование выставило наружу get(i), add(i, x), remove(i) — операции, разрушающие инвариант LIFO. Правильно — композиция: список внутри, наружу…
Middle - 129Класс сделал все поля private и добавил к каждому геттер и сеттер. Достигнута ли инкапсуляция?
Нет: инкапсуляция — это сокрытие состояния за операциями, которые держат инварианты. Сеттер на каждое поле позволяет привести объект в невозможное состояние: баланс отрицательный…
Middle - 130Что верно про полиморфизм в Java?
Динамически (по реальному классу объекта) выбираются только переопределённые методы экземпляра. Статические методы скрываются, а не переопределяются: вызов определяется…
Middle - 131В каком порядке выполняется инициализация при создании объекта подкласса?
Один раз при инициализации класса: static-поля и static-блоки — родитель, затем наследник. На каждый new: конструктор наследника сразу вызывает super(), отрабатывают поля и блоки…
Middle - 132Класс реализует два несвязанных интерфейса, в каждом из которых есть default-метод с одинаковой сигнатурой. Что произойдёт?
Ошибка компиляции: класс обязан переопределить метод. Выбрать реализацию можно явно: A.super.method().
Middle - 133Ради чего в Java 8 добавили default-методы интерфейсов?
Эволюция API без слома совместимости: добавление метода в интерфейс раньше ломало все реализации, а Collection и Iterable реализованы в бесчисленных библиотеках. Без default не…
Middle - 134Что верно про иерархию Throwable?
Throwable → Error и Exception; RuntimeException — наследник Exception. Checked = Exception минус RuntimeException. Error (OutOfMemoryError, StackOverflowError) — среда в нерабочем…
Middle - 135Метод бросает исключение внутри try, а в блоке finally стоит return. Что получит вызывающий?
Нормальный возврат: return в finally перекрывает исходный выход и проглатывает исключение — сбой бесследно исчезает. Так же действуют break и continue.
Middle - 136Почему вызов wait() принято помещать в цикл while, а не в if?
Пробуждение не гарантирует, что условие выполнено: возможны ложные пробуждения (spurious wakeup), а между notify и захватом монитора другой поток мог снова изменить состояние…
Middle - 137На каких объектах не следует синхронизироваться?
Не синхронизироваться на разделяемых или подменяемых объектах: строковых литералах (интернированы), Integer и других обёртках (кэш значений), публичном this, изменяемом поле…
Middle - 138Чем LongAdder выигрывает у AtomicLong при высокой конкуренции и в чём его ограничение?
LongAdder разносит счёт по нескольким ячейкам: потоки не бьются за одну переменную, CAS не промахивается, кэш-линия не скачет между ядрами. Итог — сумма ячеек, а не мгновенно…
Middle - 139Какие возможности даёт ReentrantLock, недоступные при использовании synchronized?
ReentrantLock добавляет tryLock (с таймаутом), lockInterruptibly, справедливый режим и несколько Condition. Цена — освобождение вручную: lock() перед try, unlock() в finally.
Middle - 140В parallel stream выполняется обращение к внешнему HTTP-сервису. Почему это опасно для всего приложения?
Parallel stream выполняется в общем ForkJoinPool.commonPool — одном на JVM, размером «ядра − 1». Блокирующий HTTP-вызов занимает его потоки, и встают все parallel stream и…
Middle - 141В каких случаях parallel stream, скорее всего, не даст выигрыша или окажется медленнее последовательного?
Выигрыша нет, когда мало данных или дешёвая операция (N × Q мало), источник плохо делится (LinkedList, Stream.iterate, итератор), есть сохранение порядка (forEachOrdered, limit…
Middle - 142Чем различаются exceptionally, handle и whenComplete у CompletableFuture?
exceptionally — только при ошибке, подменяет результат. handle — вызывается всегда, получает значение и исключение и возвращает новый результат. whenComplete — побочный эффект…
Middle - 143Когда уместен CopyOnWriteArrayList?
Каждая запись копирует весь массив — оправдано только при подавляющем преобладании чтений и небольшом размере: реестр слушателей, конфигурация.
Middle - 144Что верно про ёмкость и load factor в HashMap?
Ёмкость — степень двойки (индекс через hash & (n-1) вместо остатка), при превышении ёмкость × 0.75 таблица удваивается, а цепочка становится деревом только при длине ≥ 8 и ёмкости…
Middle - 145Почему ArrayDeque не допускает null-элементов?
null зарезервирован как сигнал «элемента нет»: poll и peek возвращают null для пустой очереди. Если бы null хранился, ответ стал бы неоднозначным.
Middle - 146Что верно про стек и кучу в JVM?
Стек — у каждого потока свой (-Xss): кадры вызовов, локальные примитивы значением и ссылки. Куча — общая (-Xmx): сами объекты. Переполнение стека — StackOverflowError, нехватка…
Middle - 147Java-приложение запускают в контейнере с лимитом памяти. Как правильно задать размер кучи?
Задавать кучу долей от лимита: -XX:MaxRAMPercentage=70–75, оставляя запас на память вне кучи (Metaspace, стеки, кодовый кэш, direct-буферы, GC). -Xmx, равный лимиту, приводит к…
Middle - 148Что невозможно из-за стирания типов?
В рантайме параметра типа нет, поэтому нельзя: new T(), new T[n], instanceof List<String>, статическое поле типа T, перегрузка m(List<String>) и m(List<Integer>) (одинаковая…
Middle - 149Зачем в сигнатуре пишут <T extends Comparable<T>>?
Граница сужает допустимые типы и открывает методы границы: без неё T — просто Object, и compareTo вызвать нельзя. После стирания T заменяется верхней границей — Comparable.
Middle - 150Чем опасно использование raw type, например List вместо List<String>?
Raw type выключает проверку дженериков для всего выражения: в список строк можно положить число, а ClassCastException появится далеко — при чтении, где компилятор вставил…
Middle - 151Зачем в JDK помимо Function<T,R> существуют IntFunction, ToIntFunction и IntPredicate?
Дженерики работают только со ссылочными типами, поэтому Function<Integer, Integer> упаковывает и распаковывает значения на каждом вызове. Специализации (IntFunction…
Middle - 152Переменной присвоили Stream, вызвали count(), а затем на той же переменной вызвали forEach(). Что произойдёт?
IllegalStateException: stream has already been operated upon or closed. Стрим — одноразовый конвейер над источником, а не хранилище данных.
Middle - 153В конвейере стоят filter и map. Почему порядок filter перед map обычно предпочтительнее обратного?
Элементы идут по конвейеру по одному: дорогое преобразование до фильтра выполняется и для отбрасываемых элементов. Чем раньше отсеять, тем меньше работы.
Middle - 154Функция значения в Collectors.toMap вернула null для одного из элементов. Что произойдёт?
NullPointerException, хотя HashMap null-значения допускает: коллектор использует merge, а он по контракту запрещает null — не отличить от отсутствия ключа.
Middle - 155Чем orElse отличается от orElseGet?
orElse(value) — аргумент вычисляется всегда, даже если значение есть (обычный порядок вычисления аргументов). orElseGet(supplier) — поставщик вызывается только при отсутствии.
Middle - 156Какие способы применения Optional считаются антипаттернами?
Антипаттерны: Optional как поле (не сериализуем, лишняя аллокация), как параметр (перекладывает проблему на вызывающего), голый get() без проверки, isPresent + get вместо map и…
Middle - 157Статическое поле SimpleDateFormat используется из нескольких потоков, и изредка возвращаются неверные даты. В чём причина и что делать?
SimpleDateFormat хранит изменяемый Calendar внутри: параллельные вызовы затирают состояние друг друга — неверные даты или исключения, причём только под нагрузкой. Замена …
Middle - 158Почему чтение файла по одному байту через FileInputStream радикально медленнее, чем через BufferedInputStream?
Дорог не байт, а системный вызов с переходом в ядро. Чтение по байту из FileInputStream — по вызову на байт; BufferedInputStream читает блок (8 КБ) за один вызов и отдаёт байты из…
Middle - 159Приложение читает файл через new FileReader(path) без указания кодировки. Чем это опасно?
Кодировка по умолчанию зависела от окружения (локаль ОС): одна сборка вела себя по-разному на машине разработчика и на сервере, данные молча портились. С Java 18 по умолчанию…
Middle - 160Почему в логировании предпочитают log.debug("user {} order {}", userId, orderId) вместо конкатенации строк?
Отложенное форматирование: строка собирается, только если уровень включён. Конкатенация вычисляется до вызова всегда — на горячем пути с выключенным debug это лишние аллокации.
Middle - 161Что такое текстовый блок и как в нём работают отступы?
Многострочный литерал в тройных кавычках: JSON, SQL, HTML без экранирования и конкатенации. Результат — обычная String. Общий отступ (по самой левой строке и закрывающим кавычкам)…
Middle - 162Что такое autoboxing и какие ловушки он приносит?
Компилятор подставляет Integer.valueOf при упаковке и intValue при распаковке. Ловушки: == работает только внутри кэша −128…127, распаковка null — NPE, каждая упаковка вне кэша …
Middle - 163Как выбираешь структуру данных под задачу? Проведи рассуждение на примере: нужно хранить сессии пользователей с быстрым поиском по id и обходом в порядке добавления.
Метод: какие операции горячие и как часто → сложность каждой у кандидатов → память и конкурентность. Поиск по id + обход в порядке добавления → LinkedHashMap; при доступе из…
Middle - 164В сервисе нужно сохранить момент оформления заказа и дату доставки, выбранную пользователем. Какие типы java.time возьмёшь и почему?
Момент оформления — Instant (в БД timestamptz, всегда UTC): событие произошло объективно, его сравнивают и сортируют глобально. Дата доставки — LocalDate: это не момент, а выбор…
Middle - 165Два потока одновременно вызывают incrementAndGet() у одного AtomicInteger. Что при этом происходит внутри и почему ни один инкремент не теряется?
CAS-цикл: прочитать значение, вычислить новое и записать, только если в памяти всё ещё старое (одна атомарная инструкция процессора). Проиграл гонку — повторить с новым значением…
Middle
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.