ch
Feedback
Библиотека собеса по Java | вопросы с собеседований

Библиотека собеса по Java | вопросы с собеседований

前往频道在 Telegram

Вопросы с собеседований по Java и ответы на них. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/08c603b6 Для обратной связи: @proglibrary_feeedback_bot

显示更多
6 485
订阅者
+124 小时
+87
+1330
帖子存档
Что такое 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

Что такое событийно-ориентированная архитектура? 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 — если нужно дождаться коммита транзакции ⚠️ Подводный камень: сложно трейсить цепочку — одно событие вызывает другое.

Для чего используется ключевое слово this? this — это ссылка на текущий объект внутри его метода или конструктора. Оно нужно для: — Разрешения конфликта имён (например, между полем класса и параметром метода).Вызова других конструкторов этого же класса.Передачи текущего объекта в качестве аргумента в методы или конструкторы других классов.Возврата ссылки на текущий объект (часто используется в паттерне Builder или для чейнинга методов). 🐸 Библиотека собеса по Java #core

💬 Обратная связь Текущий уровень сложности вопросов? 🔥 — Слишком просто, хочу сложнее 👍🏼 — В самый раз ❤️ — Иногда сложновато 😁 — Часто не понимаю 🐸 Библиотека собеса по Java

✔️ 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

👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современны
👩‍💻 Разработка на Java требует глубокого понимания не только языка, но и принципов работы JVM, многопоточности и современных фреймворков. 🎯 Курс «Java Developer. Professional» — это структурированное обучение для разработчиков, которые хотят выйти на новый уровень, освоить актуальный стек технологий и уверенно претендовать на позиции уровня Middle+. Вы получите 96 часов практической работы, на живых вебинарах разберете ключевые аспекты работы JVM, научитесь строить эффективные многопоточные приложения, освоите Spring WebFlux, Kafka, реактивный Postgres и Kubernetes. 📚Программа OTUS постоянно обновляется, соответствуя требованиям рынка, а диплом ценится работодателями. ➡️ Пройдите вступительное тестирование и присоединяйтесь к группе: https://clc.to/sfhRPw Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

Что такое идемпотентность в REST API? Идемпотентность означает, что повторный вызов одного и того же запроса не изменяет состояние сервера более одного раза. Способы реализации: — Использовать контроль состояния (если запись уже существует, не создавать её второй раз).Использовать HTTP методы по стандарту: GET, PUT, DELETE. Уже идемпотентны по спецификации.Использовать уникальный ключ (идемпотентный токен) с клиентской стороны; сервер хранит, что уже получал этот токен, и при повторе не выполняет операцию заново.В Spring → фильтры или interceptors проверяют заголовок Idempotency-Key и используют хранилище (БД, кеш) для управления повторными запросами. 🐸 Библиотека собеса по Java #core

Что такое 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

🔴 Завтра тестовое собеседование с Java-разработчиком 1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собесед
🔴 Завтра тестовое собеседование с Java-разработчиком 1 апреля(уже завтра!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Java-разработчика. Как это будет: 📂 Виктор Анохин, старший разработчик из WildBerries, будет задавать реальные вопросы и задачи разработчику-добровольцу 📂 Виктор будет комментировать каждый ответ респондента, чтобы дать понять чего от вас ожидает собеседующий на интервью 📂 В конце можно будет задать любой вопрос Виктору Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Java-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы. Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_sh_bot Реклама. О рекламодателе.

В чём разница между IO и NIO? IO (Input/Output) — это традиционная модель потоков, использующая блокирующие операции для чтения и записи данных, что может привести к задержкам, если операция занимает много времени. NIO (New IO) был введён в JDK 1.4 для улучшения производительности, предлагая неблокирующие каналы и буферы, а также поддержку асинхронных операций, что позволяет эффективно работать с большими объёмами данных или многими соединениями одновременно. 🐸 Библиотека собеса по Java #core

❓ Для чего нужен volatile? volatile — это модификатор переменной, который гарантирует: ▪️ Видимость изменений между потоками ▪️ Запрет кэширования в регистре потока Использовать стоит, когда: ▪️ Есть несколько потоков, которые читают/пишут одну переменную. ▪️ Нет сложных операций над этой переменной (например, инкрементов, которые требуют атомарности). volatile не обеспечивает атомарности, поэтому для операций «чтение-модификация-запись» нужны синхронизация или атомарные типы (AtomicInteger, AtomicReference и т.п.). 🐸 Библиотека собеса по Java #concurrency

💬 Обратная связь Ежемесячный опрос по грейдам. Проверим, выросло ли число senior'ов. Ваш грейд: 🔥 — Senior 👍🏼 — Middle ❤️ — Junior 😁 — Ещё учусь 🐸 Библиотека собеса по Java

😱 Если ваш продукт не умеет отдавать данные в формате, понятном AI-агенту, то вас просто не существует Скрипт не будет кликать по красивым кнопкам в браузере, он уйдёт к конкуренту с нормальным API. Перестроить архитектуру под машинных клиентов — это уже не хайп, а необходимое условие сохранения конкурентоспособности. Как адаптировать продукт и не исчезнуть из выдачи: — интегрировать MCP и A2A-взаимодействие, чтобы агенты могли вас читать; — научиться контролировать стоимость (лимиты, кэш, роутинг между моделями); — настроить AgentOps: трейсинг, логирование и отлов регрессий. Всё это ждёт вас на обновлённом курсе «Разработка AI-агентов». Мы специально сделали фокус на утилитарном инжиниринге и production-ready решениях. Кстати, до 29 марта можно забрать курс с большой скидкой, и стоит поторопиться — мест на потоке всё меньше. Зафиксировать цену и начать деплоить агентов без слива бюджета 👈