Співбесіда з Java: питання та практика голосом
Голосова мок-співбесіда для Java-розробників, які готуються до позицій junior, middle або senior. ШІ-інтерв’юер ставить питання на співбесіді Java, як у реальних командах: від equals/hashCode і колекцій до virtual threads, garbage collector, Spring Boot та Hibernate, а потім оцінює кожну відповідь за технічною точністю, повнотою і ясністю. Оберіть Java як технологію або завантажте резюме чи опис вакансії, щоб отримати питання під конкретну роль.
Що перевіряє співбесіда з Java
ООП і Java Core
Інкапсуляція, наслідування і поліморфізм, інтерфейси проти абстрактних класів, контракт equals/hashCode, незмінність String, records, sealed-класи та pattern matching у switch (Java 21).
Колекції зсередини
Як влаштовані HashMap, ArrayList і LinkedList, складність основних операцій, ConcurrentHashMap, TreeMap і Sequenced Collections з Java 21. Очікуйте уточнень про колізії та resize.
Багатопотоковість і virtual threads
synchronized, volatile і Java Memory Model, атомарні класи, ExecutorService і CompletableFuture, virtual threads з Java 21 і scoped values, фінальні в Java 25.
Пам’ять JVM і garbage collector
Heap, stack і Metaspace, покоління об’єктів, G1 як GC за замовчуванням, коли обирати ZGC, а також як шукати витік пам’яті через heap dump, GC-логи та JFR.
Stream API і функціональний стиль
Проміжні й термінальні операції, лінивість стрімів, Collectors, Optional, функціональні інтерфейси й лямбди, а також коли parallel stream шкодить, а не допомагає.
Spring Boot і DI
IoC-контейнер, впровадження залежностей через конструктор, scope бінів, автоконфігурація, профілі й @ConfigurationProperties, проксі та @Transactional у Spring Boot 3.x і 4.
JPA і Hibernate
Життєвий цикл сутностей і persistence context, lazy та eager завантаження, проблема N+1, оптимістичне блокування через @Version і межі транзакцій.
Тестування
JUnit 5 і Mockito, різниця між @SpringBootTest і тестовими зрізами на кшталт @WebMvcTest чи @DataJpaTest, інтеграційні тести з Testcontainers.
Питання на співбесіді Java за рівнями
Junior
Що таке контракт equals і hashCode і що буде, якщо перевизначити лише equals?
Що має бути в сильній відповіді:Рівні за equals об’єкти зобов’язані мати однаковий hashCode, а hashCode має бути стабільним, поки поля, що беруть участь у порівнянні, не змінюються. HashMap і HashSet спершу шукають кошик за hashCode, тож без перевизначеного hashCode «рівний» об’єкт потрапить в інший кошик і не знайдеться. Варто згадати, що records генерують обидва методи автоматично.
Чим ArrayList відрізняється від LinkedList і що ви оберете за замовчуванням?
Що має бути в сильній відповіді:ArrayList зберігає елементи в масиві: доступ за індексом O(1), додавання в кінець амортизовано O(1), вставка в середину O(n) через зсув. LinkedList — двозв’язний список: доступ за індексом O(n) і погана локальність у кеші процесора. На практиці майже завжди ArrayList, а для черги чи стеку — ArrayDeque.
Яка різниця між checked і unchecked винятками?
Що має бути в сильній відповіді:Checked-винятки (нащадки Exception, але не RuntimeException), як-от IOException, компілятор змушує обробити або оголосити в throws. Unchecked — нащадки RuntimeException, зазвичай це помилки програміста: NullPointerException, IllegalArgumentException. Добре згадати try-with-resources для AutoCloseable і те, що Spring загортає помилки доступу до даних у unchecked-винятки.
Чому String у Java незмінний і навіщо потрібен StringBuilder?
Що має бути в сильній відповіді:Незмінність дає потокобезпечність, дозволяє кешувати hashCode і використовувати пул рядків, а також захищає рядки, що є ключами чи параметрами, від підміни. Кожна «зміна» створює новий об’єкт, тому конкатенація в циклі породжує купу тимчасових рядків. Для цього беруть StringBuilder, який змінює внутрішній буфер.
Що таке впровадження залежностей у Spring і чому радять інжекцію через конструктор?
Що має бути в сильній відповіді:Spring-контейнер сам створює біни й передає їм залежності, тож клас не створює їх через new. Інжекція через конструктор робить залежності явними, дозволяє final-поля і тестування без Spring, а за одного конструктора @Autowired не потрібен. Інжекція в поле ховає залежності й ускладнює юніт-тести.
Middle
Як працює HashMap усередині?
Що має бути в сильній відповіді:HashMap — масив кошиків: hashCode ключа перемішується, а індекс рахується як hash & (n - 1). Колізії зберігаються у зв’язному списку, який перетворюється на червоно-чорне дерево, коли в кошику 8+ елементів і таблиця має щонайменше 64 комірки. Коли розмір перевищує capacity × 0.75, таблиця подвоюється. Сильна відповідь згадує, що змінений після вставки ключ «губиться», а сам HashMap не потокобезпечний.
Чим volatile відрізняється від synchronized?
Що має бути в сильній відповіді:volatile гарантує видимість змін між потоками і впорядкованість через happens-before, але не атомарність: count++ на volatile-полі все одно гонка. synchronized дає і взаємне виключення, і видимість для всього блоку. Для лічильників краще AtomicInteger або LongAdder, для складніших сценаріїв — ReentrantLock.
Що таке проміжні й термінальні операції в Stream API?
Що має бути в сильній відповіді:Проміжні операції (map, filter, sorted) повертають новий стрім і нічого не виконують, поки не викликано термінальну (collect, reduce, forEach). Стріми ліниві й одноразові, а операції на кшталт findFirst чи anyMatch можуть завершити обхід достроково. Варто згадати, що побічні ефекти в лямбдах — погана практика, а parallel stream використовує спільний ForkJoinPool і не підходить для блокуючого I/O.
Чому @Transactional не спрацьовує, якщо викликати метод з того самого класу?
Що має бути в сильній відповіді:Spring реалізує @Transactional через проксі, а виклик this.method() іде повз проксі, тож транзакція не відкривається. Рішення: винести метод в окремий бін або використати TransactionTemplate. Добре додати, що за замовчуванням відкат відбувається лише на unchecked-винятках і Error, а не на checked.
Що таке проблема N+1 у Hibernate і як її виправити?
Що має бути в сильній відповіді:Один запит завантажує список сутностей, а потім кожна lazy-асоціація підтягується окремим запитом — разом N+1. Виявляють через логування SQL або статистику Hibernate. Виправляють JOIN FETCH, @EntityGraph, batch fetching (@BatchSize або hibernate.default_batch_fetch_size) чи DTO-проєкціями; з fetch join колекцій і пагінацією треба бути обережним, бо Hibernate може пагінувати в пам’яті.
Senior
Коли virtual threads дають виграш, а коли ні?
Що має бути в сильній відповіді:Virtual threads — легкі потоки, які JVM монтує на невеликий пул carrier-потоків, тож блокуючий I/O не займає потік ОС. Вони виграють у сервісах з великою кількістю одночасних запитів, що чекають на мережу чи БД, але не прискорюють CPU-bound задачі. Їх не пулять, а обмежують навантаження на ресурси через Semaphore; pinning на synchronized прибрали в Java 24, але нативні виклики досі пінять. У Spring Boot 3.2+ їх вмикає spring.threads.virtual.enabled=true.
Як обрати garbage collector і як шукати витік пам’яті в продакшені?
Що має бути в сильній відповіді:G1 — збалансований GC за замовчуванням з цільовою паузою; ZGC (з Java 23 генераційний за замовчуванням) дає паузи менше мілісекунди на великих хіпах ціною додаткового CPU і пам’яті; Parallel GC підходить для батчів, де важлива пропускна здатність. Для витоку дивляться GC-логи (-Xlog:gc*) і JFR, знімають heap dump через jcmd GC.heap_dump і аналізують dominator tree в Eclipse MAT. Типові винуватці — статичні кеші без обмежень, ThreadLocal і незакриті ресурси.
Як ConcurrentHashMap забезпечує потокобезпечність і чим він кращий за Collections.synchronizedMap?
Що має бути в сильній відповіді:synchronizedMap блокує всю мапу на кожну операцію, а ітерацію треба синхронізувати вручну. ConcurrentHashMap з Java 8 читає без блокувань, вставляє в порожній кошик через CAS, а при колізії блокує лише перший вузол кошика. compute і merge атомарні для одного ключа, ітератори слабко консистентні, а null-ключі й значення заборонені, бо null у get було б неоднозначним.
Як ви проєктуєте межі транзакцій і обираєте між оптимістичним і песимістичним блокуванням?
Що має бути в сильній відповіді:Транзакції мають бути короткими: без HTTP-викликів і важких обчислень усередині, бо вони тримають з’єднання й блокування. Оптимістичне блокування через @Version додає версію в WHERE при UPDATE і кидає OptimisticLockException, якщо рядок змінили, — добре при рідких конфліктах разом з retry. Песимістичне (@Lock(PESSIMISTIC_WRITE), тобто SELECT ... FOR UPDATE) — коли конфлікти часті й повтор дорогий, з ризиком дедлоків.
Як працює автоконфігурація Spring Boot і як її налагоджувати?
Що має бути в сильній відповіді:@SpringBootApplication вмикає @EnableAutoConfiguration, а кандидати перелічені у файлі META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (spring.factories для цього в Boot 3 більше не використовується). Кожен клас обгорнутий умовами на кшталт @ConditionalOnClass, @ConditionalOnMissingBean і @ConditionalOnProperty, тож власні біни мають пріоритет. Налагоджують через звіт умов (--debug) або ендпоінт /actuator/conditions.
Як проходить мок-співбесіда з Java
- Оберіть Java (та інші технології зі свого стеку), свій рівень і мову співбесіди: українську, англійську або російську. Або завантажте резюме й опис вакансії.
- Відповідайте на кожне запитання голосом, як на справжній співбесіді.
- Отримайте оцінку кожної відповіді за точністю, повнотою та зрозумілістю і звіт зі слабкими місцями.
Як відповідати на питання з Java уголос
- →Починайте з визначення в одне речення, далі механізм, далі короткий приклад з проєкту. Структуру відповіді оцінюють не менше, ніж факти.
- →Називайте версію Java, коли це важливо: records і sealed-класи (17), virtual threads і Sequenced Collections (21), scoped values (25). Це показує, що ви не застрягли на Java 8.
- →Описуйте код словами, а не диктуйте синтаксис: «сервіс отримує репозиторій через конструктор і загортає збереження в транзакцію», а не кожну анотацію й дужку.
- →Говоріть про складність і компроміси: O(1) проти O(n), G1 проти ZGC, оптимістичне проти песимістичного блокування. Пояснити, коли рішення НЕ підходить, — сильний сигнал.
- →Прив’язуйте відповіді до реальної роботи: N+1, який ви знайшли в логах SQL, витік пам’яті з heap dump, транзакція, що не відкочувалась через self-invocation. Конкретика сильніша за підручник.
Часті запитання
Чи будуть питання про Spring, чи лише Java Core?
І те, і те. Оберіть Spring Boot, Hibernate чи інші технології разом із Java, і співбесіда поєднає питання про мову з питаннями про фреймворки. Також можна завантажити опис вакансії, щоб питання відповідали конкретній ролі.
Під яку версію Java питання?
Питання орієнтовані на сучасні LTS-версії Java 21 і 25 та Spring Boot 3.x і 4: virtual threads, records, pattern matching, сучасні GC. Класичні теми на кшталт колекцій, equals/hashCode і Java Memory Model теж є, бо їх досі питають на кожній співбесіді.
Можна пройти співбесіду українською або англійською?
Так. Мову співбесіди обираєте ви: українська, англійська або російська. Англійська зручна, якщо готуєтеся до співбесіди в іноземну компанію, де технічне інтерв’ю йде англійською.
Чи треба писати код?
Ні. Питання усні, ви відповідаєте голосом, редактора для live coding немає. Ви пояснюєте концепції, компроміси й підхід до задачі — як на технічному скринінгу. Перша співбесіда до 5 питань безкоштовна, далі від $1.75 за співбесіду без підписки.