Java Core: вопросы с ответами

161 разобранных вопросов по теме «Java Core». Каждый — с правильным ответом и пояснением.

  • ConcurrentModificationException: причина и решение?

    Модификация коллекции во время итерации не через итератор (fail-fast, в том числе в одном потоке — например, list.remove в for-each). modCount-счётчик: при следующем next() проверяется. Решения: Iterator.remove(), CopyOnWriteArrayList, ConcurrentHashMap, removeIf() (Java 8+).

  • Что такое Connection draining?

    При выводе backend из ротации — дождаться завершения активных соединений, а не обрывать. Graceful shutdown.

  • Eventual consistency — почему assertEquals сразу может упасть?

    Kafka/RabbitMQ — асинхронные. Сообщение отправлено, но ещё не обработано consumer'ом. assertEquals сразу после send → данных в БД ещё нет. Решение: Awaitility с polling, или Thread.sleep (плохо — хрупко), или callback/listener.

  • final, finally, finalize — три разных слова?

    final: класс (нельзя наследовать), метод (нельзя переопределить), поле (нельзя переприсвоить). finally: блок try-catch-finally, выполняется ВСЕГДА, в том числе при return из try. finalize(): метод Object, вызывается GC недетерминированно перед удалением (deprecated).

  • final — класс, метод, поле?

    Класс — нельзя наследовать (String, Integer). Метод — нельзя переопределить. Поле — нельзя переприсвоить ссылку, но можно менять внутреннее состояние (final List — можно add/remove). effectively final — нужна для лямбд.

  • final у класса, метода и поля?

    Класс — нельзя наследовать. Метод — нельзя переопределить. Поле — нельзя переприсваивать (но можно менять внутреннее состояние, если поле — ссылка на mutable-объект).

  • Generics: PECS. Что означает ? extends T и ? super T?

    Producer Extends, Consumer Super. extends — можно читать, нельзя писать; super — наоборот.

  • Generics: type erasure, PECS?

    Type erasure: в рантайме нет типового параметра. PECS: Producer Extends (читать), Consumer Super (писать). Wildcard <?> — только чтение как Object.

  • Generics: type erasure и PECS?

    Дженерики стираются компилятором (type erasure) — в рантайме нет информации о типовом параметре. PECS: Producer Extends, Consumer Super. List<? extends Number> — читать, List<? super Integer> — писать.

  • Generics — зачем нужны?

    Типобезопасность на этапе компиляции и устранение ручных приведений типов. Без generics: List list = new ArrayList(); list.add(123); String s = (String)list.get(0) → ClassCastException в рантайме. С generics ошибка ловится компилятором.

  • Что такое Health checks?

    Active: балансер периодически проверяет backend (HTTP GET /health, TCP connect). Passive: считает ошибки от реальных запросов. Комбинация — best practice.

  • Integer cache: почему valueOf(100)==valueOf(100) true, а valueOf(200) false?

    IntegerCache кэширует значения от -128 до 127. valueOf(100) возвращает один и тот же объект из кэша → == сравнивает ссылки → true. valueOf(200) вне кэша, создаёт новый объект каждый раз → разные ссылки → false.

  • Java 17/21: что нового для повседневной разработки?

    Records: неизменяемый data-класс с автоматическими equals/hashCode/toString и финальными полями. Sealed Classes: ограничение иерархии явным списком permits (exhaustive switch). Pattern Matching: instanceof без ручного cast со связыванием переменной, switch по типам.

  • Java — компилируемый или интерпретируемый язык?

    И то, и другое. Сначала компилируется в байт-код (.class), потом JVM его интерпретирует и компилирует «горячие» места JIT-компилятором в нативный код.

  • В чём разница: L3 vs L4 vs L7 балансировка?

    L3 (сетевой): IP-маршрутизация, ECMP. L4 (транспортный): TCP/UDP, NAT, по IP:port без разбора содержимого. L7 (прикладной): HTTP-заголовки, URL, cookies. L4 быстрее (меньше overhead), L7 гибче.

  • Что такое LazyInitializationException?

    Обращение к lazy-полю после закрытия сессии (вне транзакции), когда прокси не может догрузить данные. Решения (от лучшего к худшему): DTO-проекция (SELECT NEW), JOIN FETCH (@Query), @EntityGraph(attributePaths), @BatchSize(size=100).

  • Liquibase vs Flyway?

    Liquibase — описание изменений декларативно в XML/YAML/JSON (а также SQL), поддерживает rollback и кросс-БД абстракцию (одно описание для разных БД). Flyway — версионированные SQL-скрипты (V1__init.sql, V2__add_table.sql), проще, но без кросс-БД абстракции, а классический rollback (undo) доступен только в платной версии.

  • В чём разница: map vs flatMap?

    map: T → R, один элемент → один. flatMap: T → Stream<R> с уплощением. Пример: List<List<String>> → flatMap(Collection::stream) → плоский Stream<String>. Для Optional: flatMap избегает Optional<Optional<T>>.

  • Maven vs Gradle?

    Maven — XML-декларатив (pom.xml), строгая структура, проще. Gradle — Groovy / Kotlin DSL, гибче, быстрее (incremental builds). В Сбере и большинстве банков — Maven, в Android и многих стартапах — Gradle.

  • Optional — когда?

    Для возвращаемых значений методов. НЕ для полей (не Serializable), НЕ для параметров, НЕ для коллекций (пустая лучше). Антипаттерны: Optional.get() без isPresent(), Optional в полях, Optional<List>.

  • Optional — основные методы и антипаттерны?

    isPresent/isEmpty — проверка. ifPresent(consumer) — действие если есть (возвращает void). orElse(default) — готовое значение по умолчанию, вычисляется всегда (eager). orElseGet(supplier) — ленивый, вызывается только при отсутствии значения. map/flatMap — трансформация (flatMap когда функция сама возвращает Optional). Антипаттерн: Optional.get() без проверки и использование Optional как поля класса или параметра метода.

  • Overload vs Override — в чём разница?

    Overload (перегрузка): несколько методов с одним именем, но разными параметрами в одном классе. Компилятор выбирает статически (статическое связывание). Override (переопределение): подкласс меняет реализацию метода родителя с той же сигнатурой, а вызов разрешается динамически по фактическому типу объекта (динамическое связывание).

  • Parallel streams: в чём опасность?

    Все parallel streams делят общий ForkJoinPool.commonPool() с числом потоков по числу ядер. Если один параллельный стрим заблокировался на I/O — пул исчерпывается и остальные ждут. Решение: кастомный ForkJoinPool, например new ForkJoinPool(4).submit(() -> stream.parallel()...).get().

  • Records (Java 16+)?

    Иммутабельные data-классы: record Point(int x, int y) {}. Автоматически: конструктор, getters, equals, hashCode, toString. Нельзя наследовать (implicitly final). Можно реализовывать интерфейсы.

  • Records (Java 16+): можно ли от них наследоваться?

    Нет. Record неявно наследуется от java.lang.Record, а Java не поддерживает множественное наследование классов.

  • Records в Java — что это?

    Java 14+: компактный immutable data-класс. record User(String name, int age) {} — автоматически: канонический конструктор, аксессоры по именам компонентов (name(), age()), equals, hashCode, toString по значению. Поля private final, запись неявно final — от неё нельзя наследоваться.

  • Sealed Classes (Java 17+)?

    Ограничение иерархии наследования: sealed class Shape permits Circle, Square. Компилятор гарантирует exhaustive switch. Связка с Pattern Matching for switch (Java 21).

  • Sealed classes — зачем?

    Ограничение иерархии наследования. Хорошо работает с pattern matching.

  • Что такое Sticky sessions?

    Привязка клиента к конкретному backend. По cookie, IP, header. Проблема: неравномерная нагрузка при скейлинге. Решение: shared session storage (Redis) или stateless (JWT).

  • Что такое Stream API?

    Промежуточные (ленивые): filter, map, flatMap, sorted, distinct. Терминальные: collect, forEach, count, reduce, toList. Обработка вертикальная. Стрим одноразовый.

  • В чём разница: Stream API: промежуточные vs терминальные?

    Промежуточные (filter, map, flatMap, sorted, distinct, peek, limit, skip) — ленивые, возвращают Stream, не выполняются пока нет терминальной. Терминальные (collect, forEach, count, reduce, findFirst) запускают конвейер и возвращают результат или void, завершая стрим.

  • В чём разница: Stream API: промежуточные vs терминальные операции?

    Промежуточные (filter, map, sorted) возвращают Stream и ленивые. Терминальные (collect, forEach, count, reduce) запускают pipeline.

  • Stream API: промежуточные vs терминальные операции. Что такое ленивость?

    Промежуточные (filter, map) не выполняются до вызова терминальной (collect, forEach).

  • Stream API: что произойдёт при двух терминальных операциях?

    IllegalStateException: stream has already been operated upon or closed. Стрим одноразовый — после терминальной операции закрывается. Если нужно два результата — пересоздайте стрим или используйте Collectors (например, teeing/groupingBy).

  • В чём разница: Stream API: что такое, промежуточные vs терминальные?

    Stream — конвейер обработки данных. Промежуточные (ленивые): filter, map, flatMap, sorted. Терминальные (запускают): collect, forEach, count, reduce. Стрим одноразовый.

  • Что такое String Pool и immutability?

    Pool в heap хранит уникальные литералы. new String("hi") — новый объект вне пула. intern() добавляет в пул. Immutability: безопасность, потокобезопасность, кэширование hashCode, переиспользование в пуле.

  • В чём разница: String vs StringBuilder vs StringBuffer?

    String: immutable, при конкатенации создаёт новый объект. StringBuilder: mutable, НЕ потокобезопасный (быстрый). StringBuffer: mutable, потокобезопасный (synchronized — медленнее). В цикле конкатенация String → O(n²) из-за создания нового объекта на каждой итерации.

  • Что такое try-with-resources?

    Автоматически вызывает close() в finally. Ресурс реализует AutoCloseable. Закрытие в обратном порядке объявления. Если и try, и close бросают исключение — наружу идёт исключение тела, а close-исключение подавляется (getSuppressed()).

  • try-with-resources — какой интерфейс нужен?

    AutoCloseable (или Closeable). Ресурсы закрываются автоматически в обратном порядке объявления.

  • Что такое VRRP?

    Virtual Router Redundancy Protocol. active-standby пара балансеров. При падении primary — мгновенное переключение, IP не меняется. Используется в VK Cloud.

  • == vs equals для строк?

    == сравнивает ссылки. equals — содержимое. Из-за String Pool два литерала "abc" == "abc" дадут true, но new String("abc") == "abc" — false (new создаёт новый объект вне пула). На собесе всегда отвечать «equals для содержимого».

  • == vs equals для строк. Почему String immutable?

    == сравнивает ссылки (один объект в памяти?). equals — содержимое. String immutable: безопасность (ключи HashMap, передача в файлы/БД), потокобезопасность, кэширование hashCode, String Pool.

  • В чём разница: Абстрактный класс vs интерфейс?

    Абстрактный класс: состояние (поля), конструкторы, один наследник. Интерфейс: контракт, множественная реализация, Java 8 — default/static методы. Когда что: общее поведение + состояние → абстрактный класс; только контракт с множественной реализацией → интерфейс.

  • В чём отличие String, StringBuilder, StringBuffer?

    String — immutable. Каждая конкатенация создаёт новый объект, в цикле это O(n²) по памяти. StringBuilder — mutable, не потокобезопасный, быстрый. StringBuffer — mutable + synchronized методы, потокобезопасный, но медленнее.

  • В чём проблема — несколько связанных пунктов?

    Несколько связанных проблем. (1) Поле не final — может быть случайно перезаписано, в том числе через reflection. Для thread-safe сервиса (а Spring singleton — он всегда thread-safe должен быть) — это потенциальная проблема: singleton один на контейнер и разделяется между потоками, поэтому изменяемое состояние даёт гонки. Решение — делать поля final/неизменяемыми и инжектить через конструктор.

  • В чём разница Comparable и Comparator?

    Comparable<T> — внутри класса (метод compareTo, java.lang). Описывает «естественный» порядок. Один на класс. Comparator<T> — отдельно (метод compare, java.util). Можно сделать несколько разных Comparator'ов для одного класса под разные порядки сортировки.

  • В чём разница Factory Method и Abstract Factory?

    Factory Method — один метод, создающий объект. Часто используется для создания разных подклассов одного типа. Например, createConnection() возвращает PostgresConnection или OracleConnection. Abstract Factory — объект-фабрика с несколькими методами, порождающий целое семейство связанных продуктов.

  • В чём разница final, finally, finalize?

    final — модификатор: final class/method/field (запрет наследования, переопределения, переприсваивания). finally — блок в try-catch, выполняется ВСЕГДА (даже при исключении или return), используется для освобождения ресурсов. finalize() — устаревший метод Object, вызываемый GC недетерминированно, полагаться на него для очистки ресурсов нельзя.

  • В чём разница merge и rebase?

    merge сохраняет историю как есть — создаёт merge-коммит, объединяющий ветки, и виден факт слияния. rebase «перематывает» твои коммиты поверх свежей основной ветки — история линейная, без merge-коммитов, но хеши коммитов переписываются, поэтому rebase нельзя применять к уже опубликованным коммитам.

  • В чём разница orElse и orElseGet?

    orElse(value) — eager: значение-аргумент вычисляется ВСЕГДА, даже если Optional не пустой. orElseGet(Supplier) — lazy: лямбда вызывается только если Optional пустой, поэтому для дорогих вычислений предпочтительнее orElseGet.

  • В чём разница абстрактного класса и интерфейса?

    Абстрактный класс может иметь состояние (поля), конструктор и реализованные методы, но унаследоваться можно ТОЛЬКО от одного. Интерфейс — контракт, описывающий «что умеет», поддерживает множественную реализацию, а с Java 8 — default-методы; его методы по умолчанию public abstract.

  • В чём разница между композицией и агрегацией?

    Композиция = владение (жизненные циклы связаны), агрегация = ссылка.

  • В чём суть проблемы?

    Это «магическое» условие — фильтр, смысл которого непонятен из кода. «Берём только нечётные цены» — это бизнес-правило или баг? Если правило — оно должно быть задокументировано или вынесено в именованный предикат с говорящим названием, чтобы намерение стало явным.

  • Где видишь себя через год?

    Развиваться как Java-разработчик: вырасти от стажёра до junior'а / middle, освоить более глубокие темы (микросервисы, многопоточность, БД). Если есть конкретное направление — упомяни. Главное — показать желание расти именно как специалист, а не привязываться к должности, зарплате или смене компании.

  • Где хранятся примитивы и где объекты?

    Примитивы как локальные переменные — на стеке. Если примитив — поле объекта, он лежит внутри объекта в куче. Все объекты — в куче (heap). Статические поля и метаданные классов — в Metaspace (с Java 8 заменил PermGen).

  • Готов ли работать с legacy-кодом?

    Да, и стоит это раскрыть. В банке много legacy — никуда не деться. Хорошие фразы: «Понимаю, что legacy — это часть работы», «Это полезный опыт — понять, как развивается большая система». Спокойное согласие с раскрытием показывает зрелое отношение, в отличие от отказа или требования всё переписать.

  • Готов ли совмещать стажировку с учёбой?

    Честно. Если готов — скажи, что обычно посвящаешь учёбе X часов в неделю, стажировке готов отдать Y. Если есть гибкость в расписании — упомяни. Сбер понимает, что стажёр — студент.

  • Для чего нужен Optional?

    Контейнер, который может содержать или не содержать значение. Появился в Java 8 как альтернатива null. Помогает явно показывать в сигнатуре методов, что результат может отсутствовать.

  • Если поле не final при constructor injection — будет ошибка?

    Нет. Spring отлично инжектит и в не-final поля. Но смысл конструктора частично теряется — поле потом можно перезаписать. Конвенция: всегда final.

  • Зачем RandomGenerator вместо Random?

    RandomGenerator — общий интерфейс для всех ГСЧ в Java 17+. Это часть JEP 356: Enhanced Pseudo-Random Number Generators. Реализации: ThreadLocalRandom, SplittableRandom, различные алгоритмы (Xoshiro, L128X, L64X). Позволяет выбирать генератор по свойствам (период, splittable, jumpable) через RandomGeneratorFactory; для криптостойкости по-прежнему нужен SecureRandom.

  • Зачем нужны Liquibase или Flyway?

    Управление версиями схемы БД. Без них: разработчики применяют SQL руками, кто-то применил, кто-то нет, на проде катастрофа. С Liquibase: changeset-ы лежат в репозитории и применяются последовательно, а факт применения фиксируется в служебной таблице. Так схема во всех окружениях приводится к одному состоянию воспроизводимо.

  • К каким конструкциям применим модификатор final?

    К классу (нельзя наследовать), методу (нельзя переопределить), переменной (нельзя переприсваивать).

  • Как из List сделать неизменяемый?

    List.copyOf(list) (Java 10+) или Collections.unmodifiableList(list) — обёртка, которая бросит UnsupportedOperationException на add/remove.

  • Как написать иммутабельный класс?

    final class (нельзя наследовать). private final поля. Нет сеттеров. Конструктор с defensive copy для mutable-аргументов. Геттеры возвращают defensive copy для mutable-полей (List → Collections.unmodifiableList()), иначе наружу утекает изменяемая ссылка, ведь final защищает только ссылку, а не сам объект.

  • Как правильно?

    Два варианта в зависимости от ответа на «зачем»: (1) Если фильтр случайный или для отладки — удалить полностью. Если ничего не сломается — фильтр был лишним. (2) Если он реально нужен и работает — оставить и задокументировать, зачем он тут. Главное — честно решить судьбу кода, а не прятать его за флагами.

  • Как работает Liquibase?

    (1) Описываешь changeset'ы — изменения схемы. Формат: XML, YAML, JSON или SQL. (2) При старте Liquibase подключается к БД, смотрит в таблицу DATABASECHANGELOG — какие уже применены. (3) Применяет новые changeset'ы последовательно и фиксирует их в этой служебной таблице. История хранится в БД, а не в файле changelog.

  • Как работает protected через пакеты?

    protected-метод виден всему своему пакету (как package-private) И всем наследникам, даже из других пакетов. То есть из другого пакета можно получить доступ только через наследование, не напрямую через ссылку. Тонкость на собесе.

  • Как работает чтение файлов в Java?

    Через потоки I/O: InputStream / OutputStream — для байтов. Reader / Writer — для символов (с учётом кодировки). Buffered-обёртки (BufferedReader, BufferedInputStream) — для эффективности, читают сразу пачку и снижают число системных вызовов. Потоки нужно обязательно закрывать (try-with-resources).

  • Как разрешать конфликты при merge?

    Git помечает конфликтные участки в файле символами <<<<<<<, =======, >>>>>>>. Вручную решаешь, что оставить, удаляешь маркеры, делаешь git add и git commit. Современные IDE (IntelliJ) дают удобный визуальный merge-tool.

  • Как реализовать Singleton?

    Самый простой и правильный способ — через enum (с Java 5): public enum Database { INSTANCE; public void connect() { /* ... */ } }

  • Как сделать List неизменяемым?

    List.of(1,2,3) — Java 9+, immutable, null запрещён. List.copyOf(list) — Java 10+, глубокая неизменяемая копия. Collections.unmodifiableList(list) — обёртка (изменения в оригинале видны!). Предпочитай List.of или List.copyOf.

  • Как сортировать List по убыванию по полю?

    list.sort(Comparator.comparing(User::getAge).reversed()) или с лямбдой list.sort((a, b) -> b.getAge() - a.getAge()) — но безопаснее через Comparator.comparing.

  • Какие есть примитивные типы и их размеры?

    byte (1), short (2), int (4), long (8), float (4), double (8), char (2), boolean (~1, JVM-зависимо).

  • Какие команды Git знаешь?

    git clone — скачать репозиторий. git pull — забрать и слить изменения. git push — отправить на сервер. git add — добавить файлы в staging. git commit — зафиксировать в историю. git branch — создать / посмотреть ветки.

  • Какие могут быть «легитимные» причины?

    Их немного, и все маловероятны. (1) Тесты на edge cases — фильтр оставили из отладочного кода. (2) Какой-то странный бизнес-юзкейс типа «скидку даём только на товары с нечётной ценой» — но это нонсенс с точки зрения маркетинга. По сути, такое поведение почти всегда подозрительно и требует разбора, а не оправдания.

  • Какие модификаторы доступа есть в Java?

    private — только внутри своего класса. package-private (без модификатора, default) — внутри своего пакета. protected — пакет + наследники из других пакетов. public — отовсюду.

  • Какие операции бывают в Stream?

    Промежуточные (intermediate) — возвращают Stream, lazy: filter, map, flatMap, distinct, sorted, peek. Терминальные (terminal) — запускают конвейер: collect, reduce, forEach, count, findFirst.

  • Какие основные методы у Object?

    equals(Object) — проверка равенства. hashCode() — целочисленный хэш. toString() — строковое представление. getClass() — Class-объект. clone() — копия объекта (нужно implements Cloneable). wait(), notify(), notifyAll() — межпоточное взаимодействие. finalize().

  • Какие примитивные типы есть в Java?

    Их 8: byte (1 байт), short (2 байта), int (4 байта), long (8 байт), float (4 байта), double (8 байт), char (2 байта, UTF-16), boolean (1 бит). У каждого примитива есть класс-обёртка: Integer, Long, Boolean и так далее.

  • Какие реализации List ты знаешь?

    ArrayList — на основе массива. Доступ по индексу O(1), вставка в конец амортизированно O(1), в середину O(n). Самая популярная. LinkedList — двусвязный список. Доступ по индексу O(n), но вставка/удаление по найденному узлу O(1).

  • Какие функциональные интерфейсы из java.util.function ты знаешь?

    Consumer<T> — принимает T, ничего не возвращает (T → void). Supplier<T> — без параметров, возвращает T (() → T). Predicate<T> — принимает T, возвращает boolean. Function<T,R> — T → R. BiFunction<T,U,R> — два параметра T и U, возвращает R.

  • Какой пет-проект делал? Что было самым интересным?

    Ответ через STAR. Главное — не просто описать, что сделал, а показать рефлексию: что было сложно, чему научился, что бы переделал.

  • Когда использовать Optional?

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

  • Когда использовать Optional, а когда — нет?

    Для возвращаемых значений. НЕ для полей, параметров методов, коллекций.

  • Когда нужен Builder?

    Когда у объекта много полей (особенно опциональных), и не хочется делать конструктор с 10 параметрами. Builder делает создание объекта пошаговым и читаемым, заменяя громоздкий телескопический конструктор, и удобен для иммутабельных объектов.

  • Что такое Контракт equals/hashCode?

    Если a.equals(b) == true, то a.hashCode() == b.hashCode(). Обратное необязательно (коллизии допустимы). equals(null) → false. Переопределяешь один — переопределяй оба. Практический пример: положить объект в HashSet — иначе он не найдётся.

  • Контракт equals/hashCode. Что сломается при нарушении?

    Если a.equals(b), то hashCode совпадают. Иначе HashMap/HashSet теряют объекты.

  • Лямбда-выражения: почему переменные должны быть effectively final?

    Лямбда захватывает копию значения переменной, не ссылку на неё. Если переменная изменится после захвата — копия устареет → неочевидное поведение. Компилятор требует final или effectively final для защиты от ошибок.

  • Модификаторы доступа — порядок?

    private → (default/package-private) → protected → public. private: только в классе. default: в пакете. protected: в пакете + наследники (даже в другом пакете). public: везде.

  • Можно ли в catch ловить Throwable? Стоит ли?

    Можно, но не стоит — поймаешь и Error (OutOfMemoryError, StackOverflowError), которые обычно нельзя восстанавливать. Лови конкретные исключения.

  • Можно ли переопределить static-метод?

    Нет. Static-методы не участвуют в полиморфизме. Если в подклассе будет метод с такой же сигнатурой — это сокрытие (hiding), а не переопределение.

  • Можно ли создать свой exception от RuntimeException?

    Да, и это типовая практика. Большинство современных проектов делают свои исключения от RuntimeException — не загромождают сигнатуру методов throws. От Error не рекомендуется наследоваться — это «системные» ошибки JVM (например, OutOfMemoryError), которые приложению не положено генерировать или ловить.

  • На какие три группы делятся паттерны?

    Порождающие (Creational) — про создание объектов: Singleton, Builder, Factory Method, Abstract Factory, Prototype. Структурные (Structural) — про композицию объектов: Adapter, Decorator, Proxy, Facade, Composite, Bridge. Поведенческие (Behavioral) — про взаимодействие и распределение обязанностей: Strategy, Observer, Command, Iterator, Template Method.

  • Что такое Назови 4 принципа ООП?

    Инкапсуляция — скрытие внутреннего состояния объекта, доступ только через методы. Наследование — один класс получает поля и методы другого через extends. Полиморфизм — один интерфейс, разные реализации. Абстракция — выделение существенных характеристик и сокрытие деталей реализации за общим интерфейсом.

  • Опыт в Scrum / Agile?

    Если в учебном проекте делали daily-стендапы и спринты — это уже опыт. Можно сказать: «В курсовой работали по двухнедельным спринтам, делали ретро в конце». Если не делали — честно: «Знаю теорию (роли Scrum Master, Product Owner, команда; спринты, стендапы, ретро), на практике пока не применял».

  • От какого класса наследуются все классы в Java?

    От java.lang.Object. Это корень иерархии — даже массивы и enum'ы наследуются от него косвенно.

  • Почему final-поля и constructor injection — стандарт Senior?

    Иммутабельность зависимостей — основа thread-safe сервиса. После создания объекта его зависимости НЕ должны меняться. final гарантирует это на уровне компилятора. Конструктор делает зависимости явными — открыл класс и сразу видишь, от чего он зависит, и это легко проверить.

  • Почему shared Random может быть медленнее sequential?

    В sequential один поток последовательно дёргает nextDouble — CAS всегда успешен, никаких retry. В parallel 7 потоков одновременно пытаются обновить seed через CAS: только один успевает, остальные 6 крутят retry в цикле, и это contention сводит на нет весь выигрыш от параллелизма.

  • Почему String immutable?

    Четыре причины: 1) безопасность — строки передаются в конструкторы файлов, БД, сетевых соединений, изменение привело бы к уязвимостям; 2) потокобезопасность — можно шарить между потоками без синхронизации; 3) кэширование hashCode; 4) корректная работа String Pool.

  • Почему String в Java immutable?

    Безопасность (передача в файлы, БД, сеть), потокобезопасность, кэширование hashCode, работа String Pool.

  • Почему именно Сбер?

    Готовы 2–3 факта: масштаб (один из крупнейших IT-работодателей России), Platform V (своя облачная платформа), SberAI (GigaChat, Kandinsky), 78% оффер после стажировки. Можешь упомянуть конкретный продукт Сбера, который тебе близок, и связать его со своим опытом.

  • Разница между == и equals() для строк?

    == сравнивает ссылки. equals() сравнивает содержимое. Для строк, созданных литералом, == может вернуть true из-за String Pool, но полагаться на это нельзя.

  • Разница между == и equals(). Что вернёт someObj.equals(null)?

    == сравнивает ссылки; equals(null) по контракту должен возвращать false.

  • Что такое Расскажи жизненный цикл Maven?

    validate → compile → test → package → verify → install → deploy. validate — проверка проекта. compile — компиляция. test — юнит-тесты. package — упаковка в jar/war. verify — интеграционные тесты. install — установка артефакта в локальный ~/.m2. deploy — публикация в удалённый репозиторий.

  • Что такое Расскажи иерархию коллекций?

    Iterable → Collection. От Collection наследуются List, Set, Queue. Map стоит ОТДЕЛЬНО — она НЕ Collection. Это пары ключ-значение, не отдельные элементы. Поэтому у Map свои методы (put, get), и она не реализует Collection.

  • Что такое Расскажи контракт equals и hashCode?

    Контракт equals: рефлексивность (a.equals(a) = true), симметричность (a.equals(b) ⇔ b.equals(a)), транзитивность (a=b и b=c → a=c), консистентность (повторный вызов даёт тот же результат), equals(null) = false. Согласованность с hashCode: равные по equals объекты обязаны иметь равный hashCode (обратное необязательно).

  • Расскажи о себе — что говорить?

    Готовь рассказ на 2–3 минуты. Структура: (1) Кто ты — имя, курс, вуз, специальность. (2) Как пришёл в Java — через что попал в программирование, какие курсы/книги читал. (3) Чем занимался — проекты и стек. (4) Сильные стороны. (5) Зачем тебе эта позиция.

  • Что такое Расскажи про модификаторы доступа?

    private — только в классе. (default/package-private) — в пакете. protected — в пакете + наследникам. public — везде.

  • Расскажите про ООП: инкапсуляция, наследование, полиморфизм?

    Будьте готовы объяснить полиморфизм пятикласснику.

  • Что такое Расскажите про принципы ООП?

    Инкапсуляция, наследование, полиморфизм, абстракция. На Junior достаточно объяснить «своими словами» с примерами из жизни.

  • Что такое Расшифруй SOLID?

    S — Single Responsibility (один класс — одна ответственность). O — Open/Closed (открыт для расширения, закрыт для модификации). L — Liskov Substitution (наследник заменяет базовый тип без поломки поведения). I — Interface Segregation (много узких интерфейсов лучше одного большого). D — Dependency Inversion (зависеть от абстракций, а не от конкретных классов).

  • Сколько аппрувов нужно на merge в Сбере?

    Обычно 2 аппрува от backend-разработчиков + финальный просмотр начальника отдела перед влитием. Это compliance-требование (важная сумма банковских регуляторов).

  • Что такое Функциональные интерфейсы?

    Один абстрактный метод. Function<T,R>, Predicate<T>, Consumer<T>, Supplier<T>, UnaryOperator<T>, BiFunction, Comparator, Runnable, Callable.

  • Что такое Функциональные интерфейсы и Stream API?

    Один абстрактный метод (SAM). Function, Predicate, Consumer, Supplier, Comparator. Стрим: промежуточные (ленивые) → терминальные (запускают конвейер). Обработка вертикальная, не горизонтальная. Стрим одноразовый.

  • Что такое Функциональный интерфейс?

    Ровно один абстрактный метод (SAM). @FunctionalInterface — опциональная аннотация, но защищает от случайного добавления второго метода; лямбда компилируется и без неё. Default- и static-методы разрешены. Основные: Function<T,R>, Predicate<T>, Consumer<T>, Supplier<T>, UnaryOperator<T>.

  • Чем опасны типы-обёртки (Integer, Boolean)?

    NPE при unboxing null: Integer i = null; int x = i; → NPE. Лишняя память: Integer = 16 байт vs int = 4 байта. Медленнее: автобоксинг создаёт объекты. IntegerCache: valueOf(127) == valueOf(127) → true, но valueOf(128) == valueOf(128) → false, поэтому сравнивать нужно через equals.

  • Что такое Четыре принципа ООП своими словами?

    Инкапсуляция: банкомат — не знаешь как хранит деньги, есть методы «снять», «положить». Наследование: электросамокат наследует «транспорт». Полиморфизм: кнопка «play» — разное поведение для видео, музыки, подкаста. Абстракция: выделяешь существенное и прячешь детали за общим интерфейсом.

  • Что будет, если hashCode возвращает константу (например, return 1)?

    Все объекты попадут в один бакет HashMap. Поиск превратится в перебор связного списка (или дерева с Java 8) — деградация с O(1) до O(n) или O(log n). Карта работает, но медленно. Это любимый подвох на собесе.

  • Что будет, если hashCode() всегда возвращает одну константу?

    В Java 7 — деградация HashMap до связного списка O(n). В Java 8+ при 8 коллизиях в бакете он превращается в red-black tree, O(log n). В обоих случаях производительность резко падает.

  • Что будет, если переопределить только equals, но не hashCode?

    Сломаются hash-структуры: HashMap, HashSet, Hashtable. Положили объект — посчитался один hashCode, переопределённый equals говорит «они равны», но другой hashCode значит другой бакет. Не найдёшь, что положил: get/contains ищет в одном бакете, а объект лежит в другом. Код компилируется, исключений нет — просто нарушен контракт equals/hashCode.

  • Что вернёт someObj.equals(null)?

    false по контракту. equals не должен бросать NPE на null-аргумент.

  • Что выполнится в finally, если в try return?

    Finally выполнится перед фактическим возвратом. Если в finally тоже return — он перебьёт значение из try (анти-паттерн).

  • Что делает final для класса, метода, переменной?

    Для класса — нельзя унаследовать (final class String). Для метода — нельзя переопределить в наследнике. Для переменной — можно присвоить один раз. Для поля — становится константой (часто вместе со static).

  • Что делает i++?

    Read-modify-write: прочитать значение, добавить 1, записать обратно. Это ТРИ операции, и они НЕ атомарны. Поэтому в многопоточной среде два потока могут одновременно прочитать одно значение и оба прибавить — итог будет +1 вместо +2, часть инкрементов теряется. Для атомарности нужны AtomicInteger или synchronized.

  • Что делает mvn clean install?

    clean — удаляет директорию target/. install — проходит весь жизненный цикл (compile → test → package) и кладёт артефакт в локальный репозиторий ~/.m2. Самая часто используемая команда.

  • Что делает System.exit()?

    Принудительно завершает JVM с кодом возврата. Не выполняются finally-блоки, не закрываются ресурсы. Использовать ТОЛЬКО в экстренных случаях. В обычной разработке — не нужен.

  • Что если конфликт с коллегой?

    Подход: (1) Сначала пробую решить 1-на-1, спокойно. (2) Стараюсь понять его сторону — может, я не так понял. (3) Если не получается — иду к тимлиду, не за «он плохой», а за «помогите разрулить процесс». Конструктивный путь без обвинений и публичного давления.

  • Что знаешь о Сбере как о работодателе?

    Экосистема: СберМаркет, Самокат, Okko, СберЗдоровье, СберДевайсы, Сбер Бизнес. Platform V — собственная low-code платформа. SberAI с GigaChat и Kandinsky. Программа стажировок Sberseasons. Большая собственная IT-экосистема со своими продуктами, платформой и AI-направлением.

  • Что значит lazy в Stream?

    Промежуточные операции не выполняются сразу. Они «копят» план. Терминальная операция запускает выполнение. Поэтому stream.filter(...).map(...) без terminal — не сделает ничего. Это позволяет оптимизировать выполнение.

  • Что сломается, если hashCode() вернёт константу?

    Все объекты попадут в один bucket HashMap. Java 7: связный список O(n). Java 8+: при 8 коллизиях И capacity ≥ 64 — перестройка в red-black tree O(log n). Это лучше O(n), но деградация по сравнению с O(1).

  • Что сломается, если hashCode() вернуть константу?

    Все объекты попадут в один bucket HashMap. В Java 8+ при 8 коллизиях список превращается в red-black tree, но O(log n) вместо O(1) — всё равно деградация производительности.

  • Что сломается, если hashCode() — константа?

    Все объекты в одном bucket. Java 7: список O(n). Java 8+: при 8 коллизиях И capacity ≥ 64 — red-black tree O(log n). Деградация по сравнению с O(1).

  • Что такое ConcurrentModificationException?

    Бросается итератором в fail-fast режиме, если коллекция изменилась во время итерации не через сам итератор. Реализуется через счётчик modCount коллекции и expectedModCount итератора: если при next() они разъезжаются — исключение. Срабатывает и в одном потоке, это рантайм-проверка, а не про многопоточность.

  • Что такое default-методы в интерфейсах?

    С Java 8 в интерфейсе можно объявить метод с готовой реализацией через ключевое слово default. Это решает проблему расширения интерфейсов без поломки совместимости: добавляешь новый метод с default-реализацией, и старые классы-наследники его наследуют, не переопределяя.

  • Что такое DRY, KISS, YAGNI?

    DRY — Don't Repeat Yourself. Не дублируй код, выноси в отдельный метод/класс. KISS — Keep It Simple, Stupid. Простое решение лучше навороченного. YAGNI — You Aren't Gonna Need It. Не пиши код «на будущее», который не нужен сейчас.

  • Что такое functional interface? Приведите 3 примера из java.util.function?

    Интерфейс с одним абстрактным методом. Примеры: Function<T,R>, Predicate<T>, Consumer<T>, Supplier<T>.

  • Что такое Git Flow и Trunk-based?

    Git Flow — модель с долгоживущими ветками master, develop, feature/*, release/*, hotfix/*; подходит для релизного цикла с явными версиями. Trunk-based — все работают близко к master через короткие feature-ветки с частой интеграцией.

  • Что такое .gitignore?

    Файл со списком путей и шаблонов, которые Git должен игнорировать. Туда обычно кладут: target/ (Maven), node_modules/, .idea/ (IntelliJ), *.log, файлы с секретами (хотя секреты лучше вообще не класть в репозиторий).

  • Что такое LazyInitializationException?

    Runtime-исключение, возникающее при обращении к LAZY-полю или коллекции после закрытия сессии Hibernate. Сценарий: достал Entity в @Transactional-методе, вернул наружу; транзакция и сессия закрылись — при попытке дочитать ленивое поле летит исключение.

  • Что такое LazyInitializationException и как с ним жить?

    Попытка обратиться к lazy-полю после закрытия сессии. Решения: JOIN FETCH в запросе, @EntityGraph, DTO-проекции, OpenSessionInView (анти-паттерн в проде).

  • Что такое Observer?

    Поведенческий паттерн: Subject хранит список подписчиков (Observer) и при изменении состояния сам уведомляет всех (push-модель). В Java встречается: PropertyChangeListener, java.util.Observer (устарел), Spring Events.

  • Что такое pom.xml?

    Project Object Model — файл конфигурации Maven-проекта. Содержит: координаты артефакта (groupId, artifactId, version), зависимости, плагины, свойства, профили. Это сердце Maven-проекта.

  • Что такое Pull Request / Merge Request?

    Предложение влить твою ветку в основную (master / main / develop). Коллеги делают код-ревью, оставляют комментарии, требуют изменений. После одобрения — merge. В банках обычно нужно 2 аппрува.

  • Что такое record (Java 14+)?

    Короткий способ описать иммутабельный DTO. Автоматически генерируются: конструктор, геттеры (имя поля без get-), equals, hashCode, toString. record User(String name, int age) {} — всё. Меньше boilerplate, чем Lombok.

  • Что такое Singleton?

    Гарантирует, что в системе будет один экземпляр класса, и даёт глобальную точку доступа. Используется для конфигов, логгеров, пулов соединений. В Spring каждый @Component по умолчанию — Singleton.

  • Что такое STAR?

    Методика структурированного рассказа о ситуации. S — Situation (контекст: что за проект, кто в команде). T — Task (твоя задача в этой ситуации). A — Action (что конкретно ты делал). R — Result (что получилось, желательно с цифрами).

  • Что такое static?

    Принадлежит классу, а не объекту. static-поле общее для всех экземпляров. static-метод можно вызвать без объекта: ClassName.method(), и у него нет this. static-блок выполняется один раз при загрузке класса.

  • Что такое Strategy?

    Поведенческий паттерн: вынесение алгоритма в отдельный класс за общим интерфейсом. У клиента — поле типа интерфейса, можно подменять реализацию в рантайме. Например, разные алгоритмы сортировки, разные способы расчёта комиссии.

  • Что такое Stream API?

    Введён в Java 8. Конвейерная обработка коллекций в декларативном стиле. Поток (Stream) — это последовательность элементов с операциями. Не путать с потоком (Thread) — это про многопоточность.

  • Что такое String Pool?

    Область в heap, где хранятся уникальные строковые литералы. String s = "hi" кладёт в пул, new String("hi") — создаёт новый объект в heap.

  • Что такое String Pool? Почему String immutable?

    Безопасность, потокобезопасность, кэширование hashCode, работа String Pool.

  • Что такое try-with-resources?

    Конструкция, которая гарантирует вызов close() у ресурсов, реализующих AutoCloseable. Заменяет try-finally. При исключении в try ресурсы всё равно закроются детерминированно, а исключение из close() становится suppressed.

  • Что такое type erasure?

    Стирание дженериков во время компиляции. Последствия: нельзя new T(), нельзя instanceof T, нельзя создать массив T[].

  • Что такое var (Java 10+)?

    Ключевое слово для вывода типа локальной переменной на этапе компиляции. var list = new ArrayList<String>(); — компилятор сам определит, что это ArrayList<String>. Использовать только для локальных переменных с инициализатором, не для полей и параметров.

  • Что такое абстрактный класс? Чем отличается от интерфейса?

    Абстрактный класс может содержать состояние и реализованные методы, наследуется только один. Интерфейс — контракт, можно реализовать несколько. С Java 8 в интерфейсах появились default-методы.

  • Что такое автобоксинг и unboxing? В чём подвох?

    Автоматическое преобразование примитива в обёртку и обратно: Integer i = 5; — это int 5 заворачивается в Integer (boxing). int j = i; — обратно (unboxing). Подвох в том, что если обёртка null, при unboxing получишь NullPointerException.

  • Что такое автобоксинг и распаковка?

    Автоматическое преобразование примитива в обёртку (int → Integer) и обратно. Имеет цену: создание объекта, возможный NullPointerException при распаковке null.

  • Что такое функциональный интерфейс?

    Интерфейс с РОВНО ОДНИМ абстрактным методом (default и static не считаются). Можно реализовать лямбдой. @FunctionalInterface — необязательная аннотация для compile-time проверки.

  • Что такое функциональный интерфейс? Примеры?

    Интерфейс с ровно одним абстрактным методом. @FunctionalInterface — опциональная аннотация. Примеры: Function, Predicate, Consumer, Supplier, Runnable, Comparator.

  • Что выведет код? ```java Integer a = Integer.valueOf(127); Integer b = Integer.valueOf(127); Integer c = Integer.valueOf(128); Integer d = Integer.valueOf(128); System.out.println(a == b); System.out.println(c == d); ```

    true и false: значения от -128 до 127 обычно берутся из IntegerCache.

  • Что сломается в HashMap/HashSet, если equals переопределён, а hashCode оставлен от Object?

    Объекты могут считаться равными через equals, но попадать в разные bucket и не находиться при поиске.

новые гайды и свежие вопросы с собесов — первыми в Telegram Смотреть гайды Подписаться