Библиотека собеса по Java | вопросы с собеседований
6.48K subscribers
410 photos
9 videos
625 links
Вопросы с собеседований по Java и ответы на них.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/08c603b6

Для обратной связи: @proglibrary_feeedback_bot
Download Telegram
Для чего нужен volatile?

volatile — это модификатор переменной, который гарантирует:

▪️ Видимость изменений между потоками
▪️ Запрет кэширования в регистре потока

Использовать стоит, когда:

▪️ Есть несколько потоков, которые читают/пишут одну переменную.
▪️ Нет сложных операций над этой переменной (например, инкрементов, которые требуют атомарности).

volatile не обеспечивает атомарности, поэтому для операций «чтение-модификация-запись» нужны синхронизация или атомарные типы (AtomicInteger, AtomicReference и т.п.).

🐸 Библиотека собеса по Java

#concurrency
Please open Telegram to view this post
VIEW IN TELEGRAM
👍75
В чём разница между IO и NIO?

IO (Input/Output) — это традиционная модель потоков, использующая блокирующие операции для чтения и записи данных, что может привести к задержкам, если операция занимает много времени.

NIO (New IO) был введён в JDK 1.4 для улучшения производительности, предлагая неблокирующие каналы и буферы, а также поддержку асинхронных операций, что позволяет эффективно работать с большими объёмами данных или многими соединениями одновременно.

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Что такое DDD?

DDD (Domain-Driven Design) — подход к проектированию, при котором структура кода отражает структуру бизнес-домена.

Основные строительные блоки

Entity — объект с уникальной идентичностью. Два объекта с одним ID — один и тот же объект, даже если остальные поля разные. Пример: User, Order.

Value Object — объект без идентичности, определяется своими атрибутами. Иммутабелен. Пример: Money(100, 'USD'), Email('alice@example.com'). Два Money(100, 'USD') — одно и то же значение.

Aggregate — кластер связанных сущностей с одним корнем (Aggregate Root). Все изменения внутри агрегата — только через корень. Граница транзакции = граница агрегата. Пример: Order содержит OrderItems, но только Order — корень.

Domain Service — бизнес-операция, которая не принадлежит ни одной сущности. Пример: TransferService(fromAccount, toAccount, amount).

Repository — абстракция доступа к хранилищу для агрегатов. Один репозиторий — один агрегат.

Domain Event — факт, произошедший в домене. OrderPlaced, PaymentFailed.

Bounded Context — явная граница, внутри которой модель имеет единое значение. User в контексте Billing ≠ User в контексте Shipping.

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🔥1
Что такое идемпотентность в REST API?

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

Способы реализации:

Использовать контроль состояния (если запись уже существует, не создавать её второй раз).

Использовать HTTP методы по стандарту: GET, PUT, DELETE. Уже идемпотентны по спецификации.

Использовать уникальный ключ (идемпотентный токен) с клиентской стороны; сервер хранит, что уже получал этот токен, и при повторе не выполняет операцию заново.

В Spring → фильтры или interceptors проверяют заголовок Idempotency-Key и используют хранилище (БД, кеш) для управления повторными запросами.

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4🔥1
✔️ Java-тест: 1 запрос в коде = 10 000 запросов в БД

Код чистый, тесты быстрые, на реальных данных — pg_stat_activity в огне 👇

📦 Задание — code review

Ручка возвращает список заказов с информацией о товарах. Работает корректно, но DBA прибежал с графиком: каждый вызов делает тысячи запросов к БД.

@Entity
public class Order {
@Id
private Long id;
private Long userId;
private LocalDateTime createdAt;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
private List<OrderItem> items;
}

@Entity
public class OrderItem {
@Id
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
private Order order;

@ManyToOne(fetch = FetchType.LAZY)
private Product product;

private Integer quantity;
}

@RestController
@RequiredArgsConstructor
public class OrderController {

private final OrderRepository orderRepository;

@GetMapping("/orders")
public List<OrderDto> getOrders(@RequestParam Long userId) {
List<Order> orders = orderRepository.findByUserId(userId);

return orders.stream()
.map(order -> new OrderDto(
order.getId(),
order.getItems().stream()
.map(item -> new ItemDto(
item.getProduct().getName(),
item.getQuantity()
))
.toList()
))
.toList();
}
}


▪️ Объясни

— Точную механику N+1: где и сколько раз запросы уходят в БД в этом коде.
— Почему FetchType.EAGER «решит» проблему, но создаст другую.
— Как можно решить проблему.

Ставьте → 🔥, если нравится формат. Если нет → 🌚

💬 Решения под спойлер. Сравним, какое будет лучше.

🐸 Библиотека собеса по Java

#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥194👍4
💬 Обратная связь

Текущий уровень сложности вопросов?

🔥 — Слишком просто, хочу сложнее
👍🏼 — В самый раз
❤️ — Иногда сложновато
😁 — Часто не понимаю

🐸 Библиотека собеса по Java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1813🔥7😁1
Для чего используется ключевое слово this?

this — это ссылка на текущий объект внутри его метода или конструктора. Оно нужно для:

Разрешения конфликта имён (например, между полем класса и параметром метода).
Вызова других конструкторов этого же класса.
Передачи текущего объекта в качестве аргумента в методы или конструкторы других классов.
Возврата ссылки на текущий объект (часто используется в паттерне Builder или для чейнинга методов).

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91🔥1
Что такое событийно-ориентированная архитектура?

Event-driven architecture — это когда компоненты общаются через события, не зная друг о друге напрямую.

// Событие:
public record UserRegistered(User user) {}

// Listener:
@Component
public class SendWelcomeEmail {
@EventListener
public void handle(UserRegistered event) {
mailer.send(event.user().email(), "Welcome!");
}
}

// Публикация события:
applicationContext.publishEvent(new UserRegistered(user));


Зачем

✔️ Слабая связанность — UserService не знает о SendWelcomeEmail
✔️ Легко добавить новый listener без изменения существующего кода (Open/Closed)
✔️ Можно делать асинхронные listeners — просто добавь @Async

В Spring

— ApplicationEventPublisher для публикации
@EventListener для подписки
@TransactionalEventListener — если нужно дождаться коммита транзакции

⚠️ Подводный камень: сложно трейсить цепочку — одно событие вызывает другое.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍62🔥1
Для чего нужен @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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71🔥1
Что такое наследование?

Наследование — это механизм ООП, позволяющий создавать новый класс на основе уже существующего. Новый класс (подкласс) получает все свойства и методы родительского класса (суперкласса), что обеспечивает повторное использование кода и упрощает поддержку.

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

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍101🔥1
✔️ 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥93🤔2👍1
Какие существуют проблемы в многопоточной среде?

Основные проблемы многопоточности:

1️⃣ Race Conditionкогда результат работы зависит от порядка выполнения потоков. Например, два потока одновременно изменяют одну переменную без синхронизации.

2️⃣ Deadlockвзаимная блокировка, когда потоки ждут друг друга. Классика: поток А держит ресурс 1 и ждёт ресурс 2, а поток Б держит ресурс 2 и ждёт ресурс 1.

2️⃣ Livelockпотоки активны, но не могут продолжить работу, постоянно реагируя на действия друг друга. Например, как два человека в коридоре, которые одновременно пытаются уступить дорогу.

4️⃣ Starvationпоток никогда не получает доступ к ресурсу из-за того, что другие потоки постоянно его перехватывают.

5️⃣ Memory Visibility изменения, сделанные одним потоком, могут быть не видны другим из-за кэширования в CPU.

🐸 Библиотека собеса по Java

#concurrency
Please open Telegram to view this post
VIEW IN TELEGRAM
👍94🔥1
Сохраняешь Order в БД и отправляешь событие в Kafka. Как гарантировать, что событие не потеряется и не задвоится?

Outbox Pattern

Сохраняй событие в таблицу outbox в той же транзакции, что и бизнес-данные. Отдельный процесс читает таблицу и публикует в Kafka.

На стороне консьюмера — идемпотентность: проверяй event_id перед обработкой.

🐸 Библиотека собеса по Java

#patterns
Please open Telegram to view this post
VIEW IN TELEGRAM
👍61🔥1
Чем отличается @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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51🔥1
Что происходит с @Async методом, если он вызывается из того же класса?

Self-invocation убивает прокси

Spring создаёт AOP-прокси вокруг бина. Когда ты вызываешь this.sendEmail(), вызов идёт напрямую к объекту, минуя прокси. @Async не срабатывает, метод выполняется синхронно в том же потоке. Никакого исключения — просто тихий фейл.

private метод — та же история.

CGLIB-прокси не может переопределить private метод. Spring либо кидает предупреждение в лог, либо молча игнорирует аннотацию.

⚠️ Ещё один подводный камень

Исключения внутри @Async метода не пробрасываются к вызывающему коду. Если метод возвращает void, исключение просто теряется (уходит в AsyncUncaughtExceptionHandler). Если Future — исключение обёрнуто и бросится только при вызове get().

📌 Как правильно

Вынести @Async метод в отдельный бин и вызов пойдёт через прокси
Настроить AsyncUncaughtExceptionHandler для обработки ошибок
Возвращать CompletableFuture если нужно отслеживать результат

🐸 Библиотека собеса по Java

#spring
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83🔥1
Что такое 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
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍4🔥1
Можно ли изменить значение final переменной через рефлексию?

Технически можно, но это нарушает контракт final и приводит к непредсказуемому поведению.

Field field = obj.getClass().getDeclaredField("finalField");
field.setAccessible(true);
field.set(obj, newValue); // может не сработать


Проблемы

JVM может заинлайнить final значение при компиляции
изменения могут не отразиться из-за оптимизаций
нарушается thread-safety гарантия final

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51👏1
✔️ 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥83👍2👏1
💬 Обратная связь

Ежемесячный опрос по грейдам. Сколько среди нас джедаев мидлов?
Ваш грейд:

🔥 — Senior
👍🏼 — Middle
❤️ — Junior
😁 — Ещё учусь

🐸 Библиотека собеса по Java
Please open Telegram to view this post
VIEW IN TELEGRAM
👍36🔥20😁2015
🏃‍♀️ Мы собрали бесплатный мега-гайд по ии-агентам 👇

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

Часть 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. «Как сделать, чтобы это не развалилось через неделю?»

👍 Сохраняйте пост в избранное, чтобы не потерять.

🤫 А завтра стартует наш курс по ии-агентам
Please open Telegram to view this post
VIEW IN TELEGRAM
1👏1💯1