Skip to content

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

100 реальных вопросов с образцовыми ответами и пояснениями для уровня Junior.

Смотреть пример резюме: Java-разработчик

Тренировка флешкарточками

Интервальное повторение · Hunter Pass

Вопросы

jvm

JDK предоставляет инструменты разработки, JVM исполняет Java-байткод, а JRE содержит всё необходимое для этого исполнения.

  • JDK включает такие инструменты, как компилятор javac, а также компоненты среды выполнения.
  • javac компилирует исходные Java-файлы в платформонезависимый байткод в файлах .class.
  • JVM загружает и исполняет этот байткод в конкретной операционной системе.
  • Под JRE традиционно понимают JVM вместе с библиотеками среды выполнения, хотя современные версии Java обычно поставляются как JDK или специальные образы среды выполнения.

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

jvm

Java считается платформонезависимым языком, потому что исходный код компилируется в байткод, который могут исполнять разные реализации JVM.

  • Компилятор создаёт инструкции для JVM, а не машинный код конкретной операционной системы.
  • Для каждой поддерживаемой платформы существует своя JVM, которая интерпретирует или компилирует один и тот же байткод.
  • Переносимость всё же зависит от того, не использует ли программа API конкретной операционной системы и нативные библиотеки.

Зачем это спрашивают: Сильный ответ связывает переносимость с байткодом и платформенными реализациями JVM, а не просто повторяет известный слоган.

basics

Метод main служит стандартной точкой входа, которую Java Launcher вызывает для запуска приложения.

  • Обычно он объявляется как public static void main(String[] args).
  • public делает метод доступным для запуска, а static позволяет вызвать его без создания объекта.
  • String[] args содержит аргументы командной строки, а void означает, что метод не возвращает вызывающей стороне значение.

Зачем это спрашивают: Интервьюер хочет понять, знаете ли вы назначение частей сигнатуры точки входа, а не только помните её наизусть.

Объявление вводит переменную и её тип, а инициализация присваивает ей первое значение.

  • int count; объявляет локальную переменную с именем count.
  • count = 0; присваивает значение, а int count = 0; совмещает объявление с инициализацией.
  • Локальную переменную нужно гарантированно инициализировать до использования, и компилятор это проверяет.

Зачем это спрашивают: Вопрос проверяет знание базового синтаксиса и правила обязательной инициализации локальных переменных на этапе компиляции.

primitives

В Java есть восемь примитивных типов значений: byte, short, int, long, float, double, char и boolean.

  • byte, short, int и long представляют знаковые целые числа с разными диапазонами.
  • float и double представляют числа с плавающей точкой, причём double обеспечивает более высокую точность.
  • char хранит одну кодовую единицу UTF-16, а boolean принимает значение true или false.

Зачем это спрашивают: Интервьюер оценивает, знаете ли вы категории примитивов и назначение каждого типа в системе типов Java.

primitives

Переменная примитивного типа содержит простое значение, а ссылочная переменная указывает на объект или содержит null.

  • Примитивы имеют заданные языком типы и не предоставляют экземплярные методы.
  • Объекты создаются на основе классов и содержат поля и поведение, доступные через ссылку.
  • При присваивании примитива копируется его значение, а при присваивании ссылки копируется ссылка на тот же объект.

Зачем это спрашивают: Хороший ответ различает значения и ссылки и объясняет наблюдаемый результат присваивания.

Экземплярные и статические поля получают значения по умолчанию, а локальные переменные нужно явно инициализировать до использования.

  • Числовые поля получают ноль, поля boolean получают false, а ссылочные поля получают null.
  • Элементы массива тоже получают значение по умолчанию для своего типа.
  • Компилятор отклоняет код, если по какому-либо пути выполнения читается неинициализированная локальная переменная.

Зачем это спрашивают: Интервьюер проверяет важное различие между инициализацией состояния объекта и правилами для локальных переменных.

primitives

Расширяющее преобразование примитивов Java разрешает выполнять неявно, а сужающее направлено к типу, для которого требуется явное приведение.

  • Преобразование int в long является расширяющим и сохраняет любое возможное значение int.
  • Преобразование long в int является сужающим, потому что int не охватывает весь диапазон long.
  • Сужение может вызвать переполнение или потерю точности, причём даже расширение int в float способно потерять числовую точность.

Зачем это спрашивают: Сильный ответ объясняет и поведение компилятора, и риск потери данных.

primitivesbasics

Автоупаковка автоматически преобразует примитив в соответствующий класс-обёртку, а автораспаковка извлекает из обёртки примитивное значение.

  • При присваивании int переменной Integer может сработать автоупаковка через Integer.valueOf.
  • При присваивании Integer переменной int может сработать автораспаковка через intValue.
  • Распаковка обёртки со значением null вызывает NullPointerException, поэтому нужно учитывать возможность null.

Зачем это спрашивают: Интервьюер проверяет, понимаете ли вы удобство преобразований обёрток и связанный с null риск.

primitives

Для примитивов == сравнивает значения, а для ссылок на объекты проверяет, указывают ли обе ссылки на один объект.

  • Два разных объекта могут содержать одинаковые данные, но сравнение через == всё равно даст false.
  • Логическое равенство объектов обычно проверяют методом equals.
  • При сравнении обёртки с примитивом может произойти автораспаковка, которая скрывает различие между сравнением идентичности и значений.

Зачем это спрашивают: Вопрос проверяет, умеете ли вы избегать распространённой ошибки Java, связанной со смешением идентичности и логического равенства.

immutabilitystrings

String является неизменяемым, потому что содержимое строки нельзя изменить после создания объекта.

  • Операции concat, replace и toUpperCase возвращают новую строку, а не изменяют исходную.
  • Неизменяемость позволяет безопасно совместно использовать и кэшировать строки, а также применять их как ключи Map со стабильным равенством.
  • Многократная конкатенация в цикле создаёт много временных объектов, поэтому там обычно лучше использовать изменяемый построитель строк.

Зачем это спрашивают: Интервьюер ожидает практические следствия неизменяемости, а не только её определение.

strings

Пул строк представляет собой управляемое JVM хранилище, благодаря которому одинаковые интернированные строки могут использовать один объект.

  • Строковые литералы с одинаковым содержимым обычно ссылаются на один экземпляр из пула.
  • new String("java") явно создаёт отдельный объект, даже если такой литерал уже есть в пуле.
  • Пул экономит память, но содержимое строк всё равно следует сравнивать через equals, не полагаясь на идентичность ссылок.

Зачем это спрашивают: Сильный ответ объясняет работу пула и не делает ошибочный вывод, что строки безопасно сравнивать через ==.

strings

StringBuilder стоит использовать, когда текст многократно изменяется или собирается из частей в одном потоке.

  • append и другие методы меняют тот же построитель, а не создают новую строку на каждом шаге.
  • Это сокращает количество временных объектов в циклах и при объединении множества фрагментов.
  • После завершения сборки результат преобразуют в неизменяемый String методом toString.

Зачем это спрашивают: Интервьюер проверяет, можете ли вы связать неизменяемость String с подходящим инструментом для сборки текста.

oop

Класс определяет состояние и поведение типа, а объект является созданным во время выполнения экземпляром этого класса.

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

Зачем это спрашивают: Этот базовый вопрос проверяет, различаете ли вы определение типа и созданные на его основе экземпляры.

oop

Конструктор инициализирует новый объект, совпадает по имени с классом и не имеет возвращаемого типа.

  • Выражение new выделяет память под объект и вызывает подходящий конструктор.
  • Конструкторы можно перегружать, задавая разные списки параметров.
  • Если класс не объявляет ни одного конструктора, компилятор может добавить конструктор без аргументов по умолчанию.

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

this

this ссылается на текущий объект, для которого выполняется экземплярный метод или конструктор.

  • Оно помогает отличить поле от одноимённого параметра, например в выражении this.name = name.
  • this(...) вызывает другой конструктор того же класса и должен быть первым оператором конструктора.
  • В статическом контексте this использовать нельзя, потому что там нет текущего экземпляра.

Зачем это спрашивают: Сильный ответ охватывает доступ к текущему экземпляру, делегирование конструкторов и ограничение статического контекста.

modifiers

Статический член принадлежит классу, а не отдельному экземпляру.

  • Все экземпляры видят одно статическое поле, поэтому оно подходит для общего состояния класса или констант.
  • Статический метод можно вызвать через имя класса без создания объекта.
  • Статический код не может напрямую обращаться к экземплярным полям и методам, потому что у него нет ссылки this.

Зачем это спрашивают: Интервьюер проверяет, понимаете ли вы принадлежность и правила доступа для членов класса.

modifiers

В зависимости от места применения final запрещает повторное присваивание, переопределение метода или наследование класса.

  • Переменной final можно присвоить значение только один раз, но ссылка final не делает сам объект неизменяемым.
  • Метод final нельзя переопределить в подклассе.
  • От класса final нельзя наследоваться, что помогает сохранить его поведение и инварианты.

Зачем это спрашивают: Хороший ответ различает три применения final и не приравнивает неизменяемую ссылку к неизменяемому объекту.

oop

Инкапсуляция скрывает внутреннее состояние объекта за контролируемым публичным интерфейсом.

  • Поля часто делают private, чтобы вызывающий код не мог свободно привести объект к недопустимому состоянию.
  • Методы могут проверять изменения и сохранять инварианты класса.
  • Вызывающий код зависит от стабильного поведения, а не от текущего способа хранения данных, поэтому внутреннюю реализацию проще менять.

Зачем это спрашивают: Интервьюер хочет услышать, как контроль доступа защищает инварианты, а не только упоминание геттеров и сеттеров.

oopownership

Наследование позволяет подклассу повторно использовать и специализировать доступное поведение одного суперкласса.

  • Класс объявляет отношение через extends и наследует доступные поля и методы.
  • Конструкторы не наследуются, а конструктор подкласса явно или неявно вызывает конструктор суперкласса.
  • У каждого класса, кроме Object, только один непосредственный суперкласс, потому что Java не поддерживает множественное наследование классов.

Зачем это спрашивают: Сильный ответ включает правило одиночного наследования в Java и особое поведение конструкторов.

Закрытые вопросы

  • 21

    Чем перегрузка метода отличается от его переопределения?

    oopmethods
  • 22

    Что такое полиморфизм времени выполнения в Java?

    oop
  • 23

    Что такое абстрактный класс?

    oop
  • 24

    Что такое интерфейс в Java?

    typesinterfaces
  • 25

    Когда стоит выбрать интерфейс, а когда абстрактный класс?

    typesoopinterfaces
  • 26

    Чем отличаются уровни доступа public, protected, package-private и private в Java?

    basics
  • 27

    Для чего в Java нужны пакеты и объявления import?

    basics
  • 28

    Почему композицию часто предпочитают наследованию?

    oopownership
  • 29

    Какое значение имеет класс Object в Java?

  • 30

    Какой контракт должны соблюдать equals и hashCode?

    equals-hashcode
  • 31

    Зачем переопределять toString в Java-классе?

    methods
  • 32

    Какие гарантии предоставляет интерфейс List?

    typesinterfaces
  • 33

    Чем отличаются ArrayList и LinkedList?

    collections
  • 34

    Чем Set отличается от других типов коллекций?

    collections
  • 35

    Как HashSet определяет, что элемент является дубликатом?

    collections
  • 36

    Как Map представляет связи между ключами и значениями?

  • 37

    Как HashMap работает на базовом уровне?

    collections
  • 38

    Чем массивы отличаются от ArrayList в Java?

    collections
  • 39

    Какими распространёнными способами можно обходить коллекцию в Java?

    iterationcollections
  • 40

    Какую проблему решают дженерики в Java?

    generics
  • 41

    Почему List<Integer> не является подтипом List<Number>?

  • 42

    Что такое сырые типы и почему их следует избегать в современном Java-коде?

    generics
  • 43

    Чем проверяемые исключения отличаются от непроверяемых?

    error-handlingexceptions
  • 44

    Как совместно работают try, catch и finally?

    modifiersexceptions
  • 45

    Чем throw отличается от throws в Java?

  • 46

    Когда следует создавать собственное исключение?

    error-handlingexceptions
  • 47

    Что делает try-with-resources?

    exceptions
  • 48

    Для чего используются стек и куча в работающей Java-программе?

    memorydata-structures
  • 49

    Что делает сборка мусора в JVM?

    gcjvmcollections
  • 50

    Java передаёт аргументы по значению или по ссылке?

  • 51

    Как бы вы реализовали метод нормализации имени пользователя перед сохранением?

    normalization
  • 52

    Как написать логику суммирования только положительных целых чисел в списке с безопасной обработкой null вместо списка?

    fundamentals
  • 53

    Как удалить повторяющиеся email-адреса, сохранив исходный порядок?

  • 54

    Как посчитать частоту слов в предложении с помощью коллекций Java?

    collections
  • 55

    Как сгруппировать список заказов по идентификатору клиента?

  • 56

    Как отсортировать сотрудников сначала по убыванию зарплаты, а затем по возрастанию имени?

  • 57

    Как объединить две map остатков товаров, складывая количества для совпадающих идентификаторов?

  • 58

    Как удалить истёкшие сессии из изменяемого списка без ConcurrentModificationException?

    sessionsconcurrency
  • 59

    Как реализовать FIFO-очередь фоновых задач стандартными коллекциями Java?

    data-structurescollectionsjobs
  • 60

    Как найти пересечение двух списков без повторяющихся значений в результате?

  • 61

    Как вернуть три самых частых кода ошибок из списка?

  • 62

    Поиск пользователя в map иногда приводит к NPE. Как найти и исправить причину?

  • 63

    Как диагностировать ClassCastException при чтении значений из старой Map без типов?

  • 64

    Почему добавление элемента в List.of может упасть во время выполнения и как исправить код?

  • 65

    HashMap не находит объект-ключ, который выглядит равным сохранённому. Что нужно проверить?

    collections
  • 66

    Как реализовать проверку возраста с собственным исключением?

    error-handlingexceptionsvalidation
  • 67

    Как прочитать текстовый файл и гарантировать его закрытие при ошибке разбора?

  • 68

    Как разобрать список строк с числами, если неверные элементы нужно сообщить, а корректные сохранить?

    strings
  • 69

    На каком уровне следует ловить исключение из метода репозитория?

    error-handlingexceptions
  • 70

    Как сохранить полезные данные для отладки при преобразовании одного исключения в другое?

    error-handlingexceptions
  • 71

    Как гарантировать сброс временного флага состояния, даже если операция выбросит исключение?

  • 72

    Как реализовать потокобезопасный счётчик запросов в Java?

    concurrency
  • 73

    Как запустить десять независимых задач с фиксированным количеством рабочих потоков?

    concurrency
  • 74

    Рабочий поток прервали во время ожидания. Как должен отреагировать его код?

    concurrency
  • 75

    Как безопасно передавать очередь между потоком-производителем и потоком-потребителем?

    concurrencydata-structures
  • 76

    Два потока обновляют общий ArrayList, и часть результатов пропадает. Как это исправить?

    concurrencycollections
  • 77

    Как избежать простого дедлока, если двум методам нужны одни и те же две блокировки?

    lockingconcurrency
  • 78

    Как сделать объект конфигурации безопасным для использования из нескольких потоков?

    concurrencyconfig
  • 79

    Как найти причину IndexOutOfBoundsException в цикле?

    indexes
  • 80

    Stream-пайплайн падает с NPE в map(String::length). Как его исправить?

    ci-cdstrings
  • 81

    Как реализовать проверку на палиндром без учёта регистра и небуквенных символов?

  • 82

    Как развернуть порядок слов в предложении, не меняя порядок букв внутри слов?

  • 83

    Как найти второе по величине различное целое число в массиве?

    distinct
  • 84

    Как определить, содержит ли массив повторяющиеся значения?

  • 85

    Как реализовать бинарный поиск в отсортированном массиве int?

    algorithms
  • 86

    Как проверить, являются ли две строки анаграммами?

    strings
  • 87

    Как проверить правильность парных скобок в строке?

    validationstrings
  • 88

    Как вычислить n-е число Фибоначчи без рекурсии?

    recursion
  • 89

    Массив содержит числа от 1 до n, но одно число пропущено. Как его найти?

  • 90

    Как циклически сдвинуть список вправо на k позиций?

  • 91

    Как объединить два отсортированных массива int в один отсортированный массив?

  • 92

    Как найти первый неповторяющийся символ в строке?

    strings
  • 93

    Как удалить дубликаты из отсортированного массива на месте?

  • 94

    Как найти пару чисел, сумма которых равна заданному значению?

    equals-hashcode
  • 95

    Как посчитать итоговые суммы по категориям из списка транзакций?

    transactions
  • 96

    Как реализовать метод, который делает не более трёх повторных попыток нестабильной операции?

    flaky
  • 97

    Как безопасно преобразовать Object в целое число, если вход может быть Integer или строкой с числом?

    strings
  • 98

    Как обновлять общий кеш пользовательских сессий из нескольких потоков?

    concurrencycachingsessions
  • 99

    Как отладить метод, который возвращает правильные значения, но в непредсказуемом порядке?

  • 100

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

    ownership