Библиотека собеса по Java | вопросы с собеседований
رفتن به کانال در Telegram
Вопросы с собеседований по Java и ответы на них. По рекламе: @tproger_sales_bot Учиться у нас: clc.to/3wECtA Для обратной связи: @proglibrary_feeedback_bot
نمایش بیشتر6 378
مشترکین
-624 ساعت
-197 روز
-5130 روز
آرشیو پست ها
🏃♀️ Как провести вечер вторника с пользой для карьеры?
Включайте кружок там личное приглашение от спикера. 👆
Уже завтра в прямом эфире, разбираем архитектуру контекста в мультиагентных системах.
🤫 Секретный лут:
промик на 5.000₽. Он достанется только тем, кто придет на прямой эфир.
👉 Регистрируйтесь на трансляцию
❓ Что такое WeakReference?
WeakReference — это слабая ссылка на объект, которая не препятствует его удалению сборщиком мусора.
Если на объект есть только weak references, GC может удалить его при нехватке памяти.
WeakReference<Data> weak = new WeakReference<>(data);
data = null;
// GC может удалить объект
Data retrieved = weak.get(); // может вернуть null
Используется в кешах (WeakHashMap), где элементы могут быть удалены при нехватке памяти, или для предотвращения memory leaks в listeners.
🐸 Библиотека собеса по Java
#jvm❓ Что такое Phantom Reference?
PhantomReference — самая слабая ссылка в Java. Отличается от WeakReference тем, что get() всегда возвращает null.
Используется для отслеживания момента, когда объект удалён из памяти. После удаления объекта PhantomReference помещается в ReferenceQueue.
В отличие от finalize(), это надёжный способ отследить удаление объекта. Используется редко, в основном во внутренних механизмах или для управления off-heap памятью.
🐸 Библиотека собеса по Java
#jvm
❓ Как работает G1 GC?
G1 делит heap на равные регионы (~2048 штук) вместо фиксированных Young/Old/Perm зон. Каждый регион динамически назначается как Eden, Survivor или Old.
Ключевые фазы
→ Initial Mark — STW, помечает GC roots
→ Concurrent Mark — параллельно с приложением строит граф достижимости
→ Remark — STW, дочищает concurrent-фазу (SATB-алгоритм)
→ Cleanup / Evacuation — копирует живые объекты из регионов с наибольшим мусором (отсюда "Garbage First")
🐸 Библиотека собеса по Java
#core
❓ Что такое Optional и когда его НЕ стоит использовать?
Optional<T> — контейнер, который явно сигнализирует об отсутствии значения вместо null.
Не стоит использовать
— В полях класса (не сериализуется хорошо)
— В параметрах методов (лучше перегрузка)
— В Collections (List<Optional<T>> — антипаттерн)
Стоит использовать: как возвращаемый тип, когда значение действительно может отсутствовать.
🐸 Библиотека собеса по Java
#core
❓ Что такое false sharing в многопоточности и как его избежать?
False sharing возникает, когда разные потоки обновляют разные переменные, находящиеся в одной кэш-линии CPU.
Несмотря на отсутствие логической связи, процессор вынужден постоянно инвалидировать кэш, создавая задержки.
Последствия: высокая латентность, падение пропускной способности, резкое ухудшение производительности в hot-paths.
Как избежать:
• Разнести горячие поля по разным кэш-линиям → использовать @Contended (JDK 8+, требует -XX:-RestrictContended).
• Заполнять структуру “паддингом” вручную.
• Перепроектировать алгоритм, чтобы снизить частоту записи.
🐸 Библиотека собеса по Java
#concurrency
❓ Чем BeanFactory отличается от ApplicationContext?
BeanFactory — минималистичный IoC-контейнер. Умеет создавать бины и резолвить зависимости. Бины создаются лениво — только при первом getBean(). Используется в очень ресурсоограниченных средах (embedded-системы), в обычных Spring-приложениях практически не встречается.
ApplicationContext расширяет BeanFactory и добавляет всё, без чего реальное приложение не живёт: eager-инициализацию singleton'ов при старте, поддержку событий (ApplicationEvent), интернационализацию (MessageSource), lifecycle-коллбэки (@PostConstruct / @PreDestroy), AOP-интеграцию и работу с окружением (Environment / @Value).
⚠️ ApplicationContext создаёт все singleton-бины сразу при старте. Это значит: ошибки конфигурации (неверные зависимости, битые @Value) падают немедленно, а не при первом обращении к бину в рантайме.
🐸 Библиотека собеса по Java
#spring
🏃♀️ Мы собрали бесплатный мега-гайд по ии-агентам 👇
В первой части постов навалили жесткой базы, чтобы вправить мозги на место. Во второй дали конкретные инструменты, фреймворки и пошаговые инструкции, что нужно кодить прямо сейчас.
Часть 1. Введение, юзкейсы и реальность
Разбираемся с терминами, снимаем розовые очки и смотрим, где ИИ реально приносит бабки, а где только жжет нервы:
1. «Так что вообще считается AI-агентом?»
2. «Где тут бот, а где уже AI-агент?»
3. «Не надо пихать AI-агента в каждую задачу»
4. «Что уже можно спокойно делать через AI-агентов?»
5. «А что через AI-агентов пока лучше не трогать?»
Часть 2. Изнанка, ошибки и архитектура
Как всё это устроено под капотом, чтобы не слить бюджет и не наломать дров на старте:
6. «Можно ли просто сесть вечером и собрать себе AI-агента?»
7. «С чего вообще начать, если хочется попробовать AI-агентов»
8. «Почему AI-агент может внезапно начать творить дичь»
9. «Где AI-агенты реально экономят время, а где только добавляют возни»
10. «Почему они жрут столько денег?»
Часть 3. Хардкорная практика (Что делать руками)
Хватит теории. Открываем ноут, запускаем Cursor и делаем нормальные, отказоустойчивые системы:
11. «Почему одного промпта мало?»
12. «Почему AI-агенту мало просто “дать доступ к данным”»
13. «Если не следить за AI-агентом, он быстро начинает жить своей жизнью»
14. «Собрать демку легко. Но как же сделать нормально»
15. «Как сделать, чтобы это не развалилось через неделю?»
👍 Сохраняйте пост в избранное, чтобы не потерять.
🤫 А завтра стартует наш курс по ии-агентам
💬 Обратная связь
Ежемесячный опрос по грейдам. Сколько среди нас джедаев мидлов?
Ваш грейд:
🔥 — Senior
👍🏼 — Middle
❤️ — Junior
😁 — Ещё учусь
🐸 Библиотека собеса по Java
✔️ Java-тест: бин-синглтон, который не синглтон
Работает у одного — сломано у другого. В логах — каша из чужих данных 👇
📦 Задание — code review
Команда добавила контекст текущего пользователя в сервис через поле. Локально — всё ок.
На проде с несколькими потоками — пользователи видят чужие данные.
@Service
public class ReportService {
private User currentUser;
private ReportFilter activeFilter;
private final ReportRepository reportRepository;
public ReportService(ReportRepository reportRepository) {
this.reportRepository = reportRepository;
}
public void initContext(User user, ReportFilter filter) {
this.currentUser = user;
this.activeFilter = filter;
}
public List<Report> getReports() {
if (currentUser == null) {
throw new IllegalStateException("Context not initialized");
}
return reportRepository.findByUserAndFilter(
currentUser.getId(),
activeFilter
);
}
public ReportSummary getSummary() {
List<Report> reports = getReports();
return ReportSummary.calculate(reports, currentUser);
}
}
▪️ Объясни
— Какой скоуп у бина по умолчанию в Spring и почему это делает поля-состояния опасными.
— Почему synchronized над методами не является правильным решением здесь.
— Как переписать код, чтобы работало.
Ставьте → 🔥, если нравится формат. Если нет → 🌚
💬 Решения под спойлер. Сравним, какое будет лучше.
🐸 Библиотека собеса по Java
#practise❓ Можно ли изменить значение final переменной через рефлексию?
Технически можно, но это нарушает контракт final и приводит к непредсказуемому поведению.
Field field = obj.getClass().getDeclaredField("finalField");
field.setAccessible(true);
field.set(obj, newValue); // может не сработать
Проблемы
— JVM может заинлайнить final значение при компиляции
— изменения могут не отразиться из-за оптимизаций
— нарушается thread-safety гарантия final
🐸 Библиотека собеса по Java
#core❓ Что такое N+1 проблема в Hibernate и чем JOIN FETCH отличается от @EntityGraph?
Загружаешь список из N сущностей, а потом для каждой Hibernate делает отдельный SELECT за связанной коллекцией. 1 запрос на список + N запросов на детали = катастрофа на проде.
// Загружаем 100 заказов — получаем 101 запрос
List<Order> orders = orderRepo.findAll();
orders.forEach(o -> o.getItems().size()); // LAZY — N запросов здесь
JOIN FETCH vs @EntityGraph
JOIN FETCH — пишешь в JPQL явно:
@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.status = :s")
List<Order> findWithItems(@Param("s") Status s);
Гибко, но размножается: для каждой комбинации связей нужен свой метод.
@EntityGraph — декларативно, переиспользуемо:
@EntityGraph(attributePaths = {"items", "items.product"})
List<Order> findByStatus(Status status);
⚠️ Узкие места
JOIN FETCH с коллекциями → если fetch двух коллекций одновременно → MultipleBagFetchException. Hibernate не умеет делать два JOIN FETCH на Bag-коллекции в одном запросе.
@EntityGraph → на больших данных легко получить декартово произведение в результирующем SQL и огромный набор дублирующихся строк. Используй DISTINCT или Set вместо List.
🐸 Библиотека собеса по Java
#spring❓ Что происходит с @Async методом, если он вызывается из того же класса?
Self-invocation убивает прокси
Spring создаёт AOP-прокси вокруг бина. Когда ты вызываешь this.sendEmail(), вызов идёт напрямую к объекту, минуя прокси. @Async не срабатывает, метод выполняется синхронно в том же потоке. Никакого исключения — просто тихий фейл.
private метод — та же история.
CGLIB-прокси не может переопределить private метод. Spring либо кидает предупреждение в лог, либо молча игнорирует аннотацию.
⚠️ Ещё один подводный камень
Исключения внутри @Async метода не пробрасываются к вызывающему коду. Если метод возвращает void, исключение просто теряется (уходит в AsyncUncaughtExceptionHandler). Если Future — исключение обёрнуто и бросится только при вызове get().
📌 Как правильно
— Вынести @Async метод в отдельный бин и вызов пойдёт через прокси
— Настроить AsyncUncaughtExceptionHandler для обработки ошибок
— Возвращать CompletableFuture если нужно отслеживать результат
🐸 Библиотека собеса по Java
#spring
❓ Чем отличается @Transactional(propagation = REQUIRES_NEW) от NESTED?
И когда использование NESTED может неожиданно упасть?
REQUIRES_NEW — полностью приостанавливает текущую транзакцию и открывает новую, независимую. Свой коннект к БД, свой коммит и роллбэк. Внешняя транзакция об этом не знает.
NESTED — работает внутри той же транзакции через savepoint. Если вложенный метод откатится — откат только до savepoint'а, внешняя транзакция продолжает жить. Один коннект, один итоговый коммит.
⚠️ Когда NESTED неожиданно падает
1. JPA + Hibernate
JpaTransactionManager не поддерживает savepoints из коробки — получишь NestedTransactionNotSupportedException. Нужна явная донастройка, и то ненадёжно.
2. База не умеет savepoints
MySQL с движком MyISAM, некоторые конфигурации H2 — savepoints просто не поддерживаются на уровне драйвера.
3. Self-invocation
// proxy не задействован → NESTED полностью игнорируется
this.nestedMethod();
🐸 Библиотека собеса по Java
#spring❓ Сохраняешь Order в БД и отправляешь событие в Kafka. Как гарантировать, что событие не потеряется и не задвоится?
✅ Outbox Pattern
Сохраняй событие в таблицу outbox в той же транзакции, что и бизнес-данные. Отдельный процесс читает таблицу и публикует в Kafka.
На стороне консьюмера — идемпотентность: проверяй event_id перед обработкой.
🐸 Библиотека собеса по Java
#patterns
❓ Какие существуют проблемы в многопоточной среде?
Основные проблемы многопоточности:
1️⃣ Race Condition — когда результат работы зависит от порядка выполнения потоков. Например, два потока одновременно изменяют одну переменную без синхронизации.
2️⃣ Deadlock — взаимная блокировка, когда потоки ждут друг друга. Классика: поток А держит ресурс 1 и ждёт ресурс 2, а поток Б держит ресурс 2 и ждёт ресурс 1.
2️⃣ Livelock — потоки активны, но не могут продолжить работу, постоянно реагируя на действия друг друга. Например, как два человека в коридоре, которые одновременно пытаются уступить дорогу.
4️⃣ Starvation — поток никогда не получает доступ к ресурсу из-за того, что другие потоки постоянно его перехватывают.
5️⃣ Memory Visibility — изменения, сделанные одним потоком, могут быть не видны другим из-за кэширования в CPU.
🐸 Библиотека собеса по Java
#concurrency
✔️ Java-тест: задача выполняется, результат теряется
Никаких ошибок в логах. Никаких алертов. Данные просто не сохраняются 👇
📦 Задание — code review
Сервис нотификаций: после оплаты заказа — отправить email и записать событие в БД. Оба действия независимы, сделали асинхронно.
@Service
@RequiredArgsConstructor
public class NotificationService {
private final EmailClient emailClient;
private final EventRepository eventRepository;
private final Executor taskExecutor;
public void notifyOrderPaid(Order order) {
CompletableFuture.runAsync(
() -> emailClient.sendOrderConfirmation(order),
taskExecutor
);
CompletableFuture.runAsync(
() -> {
Event event = Event.orderPaid(order.getId());
eventRepository.save(event);
},
taskExecutor
);
}
}
▪️ Объясни
— Почему исключения из runAsync полностью проглатываются и как это работает внутри.
— Чем отличается поведение runAsync от supplyAsync в контексте обработки ошибок.
— Как переписать код так, чтобы: (1) ошибки логировались, (2) один сбой не блокировал другую задачу, (3) вызывающий код мог знать об итоге.
Ставьте → 🔥, если нравится формат. Если нет → 🌚
💬 Решения под спойлер. Сравним, какое будет лучше.
🐸 Библиотека собеса по Java
#practise❓ Что такое наследование?
Наследование — это механизм ООП, позволяющий создавать новый класс на основе уже существующего. Новый класс (подкласс) получает все свойства и методы родительского класса (суперкласса), что обеспечивает повторное использование кода и упрощает поддержку.
Наследование реализуется с помощью ключевого слова extends. Подкласс может расширять или переопределять поведение суперкласса, а также добавлять новые поля и методы. Важно помнить, что в Java класс может наследоваться только от одного суперкласса.
🐸 Библиотека собеса по Java
#core
❓ Для чего нужен @Value в Spring?
@Value внедряет значения из property файлов или environment variables в поля, параметры методов или конструкторов.
@Value("${app.name}")
private String appName;
@Value("${app.timeout:30}")
private int timeout; // 30 - default значение
@Value("#{systemProperties['user.name']}")
private String userName; // SpEL выражение
Поддерживает
— property placeholders ${...}
— SpEL выражения #{...}
— значения по умолчанию через ":"
Альтернатива для группы свойств: @ConfigurationProperties.
🐸 Библиотека собеса по Java
#spring