ru
Feedback

Не попадитесь на канал ботавода! Telemetrio находит и помечает такие каналы 👉 Хотите видеть метку — оформите подписку

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

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

Открыть в Telegram

Вопросы с собеседований по Java и ответы на них. По рекламе: @tproger_sales_bot Учиться у нас: clc.to/3wECtA Для обратной связи: @proglibrary_feeedback_bot

Больше
6 378
Подписчики
-624 часа
-197 дней
-5130 дней
Архив постов
❓ Расскажите о паттерне Builder Builder — это порождающий паттерн, который позволяет создавать сложные объекты пошагово, разделяя процесс конструирования и представление. Простыми словами: вместо конструктора с десятком параметров, вы собираете объект по частям, вызывая понятные методы. ▪️ Пример: HTTP-клиент с множеством необязательных настроек: таймауты, заголовки, ретраи, прокси. Конструктор с 10 параметрами нечитаем, а Builder решает это.
public class HttpClient {
    private final String baseUrl;
    private final int connectTimeout;
    private final int readTimeout;
    private final Map<String, String> headers;
    private final int maxRetries;

    private HttpClient(Builder builder) {
        this.baseUrl = builder.baseUrl;
        this.connectTimeout = builder.connectTimeout;
        this.readTimeout = builder.readTimeout;
        this.headers = builder.headers;
        this.maxRetries = builder.maxRetries;
    }

    public static class Builder {
        private final String baseUrl;           // обязательный
        private int connectTimeout = 5000;      // значение по умолчанию
        private int readTimeout = 10000;
        private Map<String, String> headers = new HashMap<>();
        private int maxRetries = 3;

        public Builder(String baseUrl) {
            this.baseUrl = baseUrl;
        }

        public Builder connectTimeout(int ms) {
            this.connectTimeout = ms;
            return this;
        }

        public Builder readTimeout(int ms) {
            this.readTimeout = ms;
            return this;
        }

        public Builder header(String key, String value) {
            this.headers.put(key, value);
            return this;
        }

        public Builder maxRetries(int retries) {
            this.maxRetries = retries;
            return this;
        }

        public HttpClient build() {
            return new HttpClient(this);
        }
    }
}

// Использование
HttpClient client = new HttpClient.Builder("https://api.example.com")
    .connectTimeout(3000)
    .header("Authorization", "Bearer token")
    .maxRetries(5)
    .build();
▪️ Когда использовать — Объект имеет множество параметров (особенно необязательных) — Нужна immutable-объект с удобным созданием — Хотите избежать telescoping constructor (конструктор в конструкторе) ▪️ Builder vs конструктор — Конструктор: подходит, если параметров 2–3 и все обязательные — Builder: если параметров больше 4 или есть необязательные ▪️ Минус Дублирование полей между классом и билдером. Lombok @Builder решает это автоматически. 🐸 Библиотека собеса по Java #patterns

❓ Расскажите о паттерне Flyweight Flyweight — это структурный паттерн, который позволяет вместить большее количество объектов в отведённую оперативную память за счёт разделения общего состояния между объектами. Простыми словами: вместо создания тысяч похожих объектов, вы создаёте несколько объектов-легковесов с общими данными и передаёте уникальные данные извне при использовании. ▪️ Пример Текстовый редактор, где каждая буква — это объект. Если создавать отдельный объект для каждой буквы с полным набором свойств (шрифт, размер, цвет), миллион символов займут гигабайты памяти.
// Flyweight — легковес с общим состоянием class CharacterStyle { private final String font; // внутреннее состояние private final int size; // (intrinsic) private final String color; public CharacterStyle(String font, int size, String color) { this.font = font; this.size = size; this.color = color; } public void render(char character, int x, int y) { // внешнее состояние System.out.println("Рендер '" + character + "' в позиции (" + x + "," + y + ")"); } } // Фабрика для переиспользования flyweight-объектов class StyleFactory { private Map<String, CharacterStyle> styles = new HashMap<>(); public CharacterStyle getStyle(String font, int size, String color) { String key = font + size + color; return styles.computeIfAbsent(key, k -> new CharacterStyle(font, size, color)); } } // Использование StyleFactory factory = new StyleFactory(); // Миллион символов используют всего несколько объектов стилей CharacterStyle arial12 = factory.getStyle("Arial", 12, "black"); arial12.render('H', 0, 0); arial12.render('e', 10, 0); arial12.render('l', 20, 0); arial12.render('l', 30, 0); arial12.render('o', 40, 0);
▪️ Когда использовать — Приложение создаёт огромное количество однотипных объектов — Объекты потребляют много памяти — Большую часть состояния можно вынести за пределы объекта — Приложение не зависит от идентичности объектов (можно переиспользовать) ▪️ Минусы — Усложнение кода из-за разделения состояния — Flyweight должен быть immutable для безопасного переиспользования 🐸 Библиотека собеса по Java #patterns

🗓 14 мая в 19:00 (Мск) встречаемся в онлайне. Тема: Почему AI-продукты на базе LLM ломаются и как сделать, чтобы работало. В кружке выше Эмиль Сатаев рассказал, какие именно проблемы с LLM в проде будем разбирать. Что в программе:
- Разберем реальные кейсы стартапов и ограничения LLM. - Обсудим рабочие архитектуры: RAG, human-in-the-loop, контроль качества. - Ответим на ваши вопросы и разберем кейсы участников.
🎁 Бонусы: в конце вебинара подарим промокод на скидку 10.000 ₽ на курсы и разыграем подписки на полезные AI-сервисы. 👉 Зарегистрироваться на вебинар

❓ Расскажите о паттерне Prototype Prototype — это порождающий паттерн, который позволяет копировать объекты, не вдаваясь в подробности их реализации. Простыми словами: вместо создания объекта с нуля через конструктор, вы клонируете уже существующий экземпляр. ▪️ Пример: Система отчетов, где базовая конфигурация отчета сложная (подключение к БД, загрузка шаблонов, настройка форматирования). Вместо каждый раз создавать отчет заново, клонируем прототип.
// Прототип abstract class Report implements Cloneable { protected String template; protected DatabaseConnection dbConnection; protected Map<String, Object> settings; // Сложная инициализация public Report() { this.dbConnection = new DatabaseConnection(); // затратная операция this.settings = loadDefaultSettings(); // загрузка из файла } @Override public Report clone() { try { Report cloned = (Report) super.clone(); // Глубокое копирование для изменяемых полей cloned.settings = new HashMap<>(this.settings); return cloned; } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } abstract void generate(); } class SalesReport extends Report { void generate() { System.out.println("Генерация отчета по продажам"); } } // Использование Report prototype = new SalesReport(); // долгая инициализация // Быстрое создание копий Report report1 = prototype.clone(); Report report2 = prototype.clone(); report2.settings.put("period", "Q2"); // изменяем только нужные параметры
▪️ Когда использовать — Создание объекта затратно (сложная инициализация, обращение к БД, парсинг файлов) — Нужно избежать привязки к конкретным классам при создании копий — Объекты различаются только состоянием, а не поведением ▪️ Важно: Shallow vs Deep Copy Shallow copy — копируются только примитивы, ссылки на объекты остаются теми же Deep copy — создаются копии вложенных объектов ▪️ Альтернативы clone() — Copy constructor: new Report(original) — Статический метод: Report.copy(original) — Сериализация: для очень сложных объектов ▪️ Минус Клонирование объектов с циклическими ссылками может быть сложным. 🐸 Библиотека собеса по Java #patterns

✔️ Java-тест: транзакция, которая не откатывается @Transactional стоит, исключение летит. Данные в БД остаются. Почему? 📦 Задание — code review Команда добавила транзакцию на метод сохранения заказа. При ошибке валидации данные всё равно коммитятся в базу. @Transactional на месте, но не работает.
public class CheckedBusinessException extends Exception {
    public CheckedBusinessException(String message) {
        super(message);
    }
}

@Service
public class OrderService {

    private final OrderRepository orderRepository;
    private final InventoryService inventoryService;

    @Transactional
    public void placeOrder(Order order) throws CheckedBusinessException {
        orderRepository.save(order);
        inventoryService.reserveStock(order);
    }
}

@Service
public class InventoryService {

    public void reserveStock(Order order) throws CheckedBusinessException {
        if (order.getQuantity() > availableStock) {
            throw new CheckedBusinessException("Not enough stock");
        }
    }
}
▪️ Почему @Transactional не откатывает изменения при CheckedBusinessException? ▪️ Как добиться rollback в этом коде Ставьте → 🔥, если нравится формат. Если нет → 🌚 💬 Решения под спойлер. Сравним, какое будет лучше. 🐸 Библиотека собеса по Java #practise

🦾 Почему ваши AI-продукты на базе LLM ломаются (и как это чинить)? Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или
🦾 Почему ваши AI-продукты на базе LLM ломаются (и как это чинить)? Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало». 🗓 Когда: 14 мая в 19:00 МСК ⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы 🧑🏻‍💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы. 🎁 Главный бонус для онлайна: Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps. 👉 Занять место на вебинаре

❓ Расскажите о паттерне Abstract Factory Abstract Factory — это порождающий паттерн, который создает семейства связанных объектов без привязки к конкретным классам. Простыми словами: вы создаете не один объект, а целый набор совместимых между собой объектов. ▪️ Пример: Система уведомлений, которая работает с разными провайдерами (AWS, Firebase). Для каждого провайдера нужны свои клиенты для отправки email, SMS и push-уведомлений.
// Абстрактные продукты interface EmailSender { void send(String to, String message); } interface SmsSender { void send(String phone, String message); } // Абстрактная фабрика interface NotificationFactory { EmailSender createEmailSender(); SmsSender createSmsSender(); } // AWS реализация class AwsEmailSender implements EmailSender { public void send(String to, String message) { System.out.println("Отправка через AWS SES: " + to); } } class AwsSmsSender implements SmsSender { public void send(String phone, String message) { System.out.println("Отправка через AWS SNS: " + phone); } } class AwsNotificationFactory implements NotificationFactory { public EmailSender createEmailSender() { return new AwsEmailSender(); } public SmsSender createSmsSender() { return new AwsSmsSender(); } } // Аналогично FirebaseNotificationFactory... // Использование NotificationFactory factory = new AwsNotificationFactory(); EmailSender email = factory.createEmailSender(); SmsSender sms = factory.createSmsSender(); // Гарантия: оба сервиса работают через AWS
▪️ В чем отличие от Factory Method — Factory Method создает один продукт — Abstract Factory создает семейство продуктов (email + sms + push) ▪️ Когда использовать Когда нужны наборы связанных объектов, которые должны работать вместе (клиенты для разных облаков, драйверы БД, парсеры форматов). ▪️ Минус Сложно добавить новый тип продукта — придется менять все фабрики. 🐸 Библиотека собеса по Java #patterns

❓ Расскажите о паттерне Factory Method Factory Method — порождающий паттерн, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов. 🔹 Когда использовать: Когда заранее неизвестны типы и зависимости объектов, или когда нужно делегировать создание объектов подклассам. 🔹 Как работает: Создается абстрактный метод для создания объектов, а конкретные подклассы переопределяют его, возвращая нужные типы. 🔹 Плюсы: — избавляет от привязки к конкретным классам; — упрощает добавление новых типов продуктов; — следует Open/Closed Principle. 🐸 Библиотека собеса по Java #patterns

❓ Расскажите о паттерне Adapter Adapter (Адаптер) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли "переходника" между двумя интерфейсами. 🔹 Когда использовать: Когда нужно использовать существующий класс, но его интерфейс не соответствует требуемому. Например, при интеграции сторонних библиотек или работе с легаси-кодом. 🐸 Библиотека собеса по Java #patterns

❓ Расскажите о паттерне Singleton? Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему. 🔹 Основные характеристики: — приватный конструктор запрещает создание экземпляров извне; — статический метод getInstance() возвращает единственный экземпляр; — статическое поле для хранения экземпляра. 🔹 Когда использовать: — объект содержит глобальное состояние; — создание объекта ресурсозатратно; — нужен единый координатор действий; — логически должен быть один экземпляр. 🐸 Библиотека собеса по Java #patterns

❓ Расскажите о паттерне Strategy? Strategy — это поведенческий паттерн, который позволяет определить семейство алгоритмов, инкапсулировать каждый из них и сделать их взаимозаменяемыми. Когда использовать: — есть несколько способов выполнения одной операции; — нужно избежать множественных if-else или switch; — алгоритмы должны выбираться в runtime. Преимущества: соблюдение Open/Closed Principle, устранение условных операторов, гибкость выбора алгоритма. 🐸 Библиотека собеса по Java #patterns

❓ Как работает HashMap внутри? Что происходит при коллизии и при достижении load factor? HashMap — массив бакетов (Node[] table). Ключ хешируется, хеш определяет индекс бакета: index = hash & (capacity - 1 Что происходит при put(key, value): Считается hash(key) — не просто hashCode(), а с дополнительным перемешиванием старших битов ((h = key.hashCode()) ^ (h >>> 16)). Это снижает коллизии при маленьком размере таблицы. Находится бакет по индексу. Если пустой — кладём первым. Если нет — коллизия. 🔹 Коллизия: До Java 8 → связный список в бакете. Поиск O(n) в худшем случае. С Java 8 → когда в бакете больше 8 элементов и capacity >= 64, список превращается в красно-чёрное дерево. Поиск становится O(log n). Обратно в список — при сжатии ниже 6 элементов.
// Упрощённо: Node в списке или TreeNode в дереве
static class Node<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}
🔹 Load factor и resize: По умолчанию capacity = 16, loadFactor = 0.75. Порог = capacity * loadFactor = 12. Как только элементов стало больше 12 — начинается resize(): таблица удваивается до 32, все элементы перераспределяются по новым бакетам. Это O(n) операция. Поэтому если заранее знаете размер — задавайте начальную ёмкость:
// Хотим 1000 элементов без resize:
// 1000 / 0.75 ≈ 1334, берём следующую степень двойки
Map<String, Integer> map = new HashMap<>(2048);
🐸 Библиотека собеса по Java #core

❓ Как работает HashMap внутри? Что происходит при коллизии и при достижении load factor? HashMap — массив бакетов (Node[] table). Ключ хешируется, хеш определяет индекс бакета: index = hash & (capacity - 1 Что происходит при put(key, value): Считается hash(key) — не просто hashCode(), а с дополнительным перемешиванием старших битов ((h = key.hashCode()) ^ (h >>> 16)). Это снижает коллизии при маленьком размере таблицы. Находится бакет по индексу. Если пустой — кладём первым. Если нет — коллизия. 🔹 Коллизия: До Java 8 → связный список в бакете. Поиск O(n) в худшем случае. С Java 8 → когда в бакете больше 8 элементов и capacity >= 64, список превращается в красно-чёрное дерево. Поиск становится O(log n). Обратно в список — при сжатии ниже 6 элементов.
// Упрощённо: Node в списке или TreeNode в дереве
static class Node<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;
}
🔹 Load factor и resize: По умолчанию capacity = 16, loadFactor = 0.75. Порог = capacity * loadFactor = 12. Как только элементов стало больше 12 — начинается resize(): таблица удваивается до 32, все элементы перераспределяются по новым бакетам. Это O(n) операция. Поэтому если заранее знаете размер — задавайте начальную ёмкость:
// Хотим 1000 элементов без resize:
// 1000 / 0.75 ≈ 1334, берём следующую степень двойки
Map<String, Integer> map = new HashMap<>(2048);
🐸 Библиотека собеса по Java #core

✔️ Java-тест: кэш, который врёт Метод возвращает устаревшие данные. Иногда и только на нескольких потоках. Воспроизвести локально — нереально 👇 📦 Задание — code review Команда добавила простой in-memory кэш для тяжёлых вычислений. На одном потоке работает идеально. На проде с нагрузкой — иногда возвращает старый результат или null.
@Component
public class PricingCache {

    private final Map<String, BigDecimal> cache = new HashMap<>();
    private final PricingEngine pricingEngine;

    public PricingCache(PricingEngine pricingEngine) {
        this.pricingEngine = pricingEngine;
    }

    public BigDecimal getPrice(String productId) {
        if (cache.containsKey(productId)) {
            return cache.get(productId);
        }
        BigDecimal price = pricingEngine.calculate(productId);
        cache.put(productId, price);
        return price;
    }

    public void invalidate(String productId) {
        cache.remove(productId);
    }

    public void invalidateAll() {
        cache.clear();
    }
}
▪️ Объясни — В чём проблема в коде — Как переписать getPrice верно Ставьте → 🔥, если нравится формат. Если нет → 🌚 💬 Решения под спойлер. Сравним, какое будет лучше. 🐸 Библиотека собеса по Java #practise

❓ Чем отличается ReentrantLock от synchronized? 🔹 synchronized — встроенный монитор JVM. Прост, но ограничен: — нельзя прервать ожидание — нет tryLock — нельзя узнать, занят ли монитор 🔹 ReentrantLock из java.util.concurrent.locks — явная блокировка с расширенными возможностями:
ReentrantLock lock = new ReentrantLock();

// Попытка без ожидания
if (lock.tryLock()) {
    try {
        // критическая секция
    } finally {
        lock.unlock(); // обязателен!
    }
}

// С таймаутом
if (lock.tryLock(500, TimeUnit.MILLISECONDS)) { ... }

// С прерыванием
lock.lockInterruptibly();
🔹 Когда synchronized Простые сценарии, нет нужды в доп. функциях, меньше кода и риска ошибок. 🔹 Когда ReentrantLock Нужен tryLock, таймаут, прерывание, несколько Condition, или fairness. 🐸 Библиотека собеса по Java #concurrency

❓ Для чего нужен @Conditional в Spring? @Conditional регистрирует бин только при выполнении определённого условия.
@Bean
@Conditional(WindowsCondition.class)
public Service windowsService() {
    return new WindowsService();
}

class WindowsCondition implements Condition {
    public boolean matches(ConditionContext context, 
                          AnnotatedTypeMetadata metadata) {
        return System.getProperty("os.name")
            .contains("Windows");
    }
}
Spring Boot предоставляет готовые: @ConditionalOnProperty, @ConditionalOnClass, @ConditionalOnMissingBean. 🐸 Библиотека собеса по Java #spring

Осталось всего 4 места на курс по ИИ-агентам. 30 апреля закрываем набор окончательно. В ГС честно рассказали: — Кому курс не подойдет; — Какой хардкор в программе (LangGraph, AutoGen, CrewAI); — Как мы даем токены, чтобы вы не тратили свои деньги. 🏃‍♀️ Записаться, пока есть места

❓ В чем разница между параллелизмом и многопоточностью? Многопоточность — это способность программы выполнять несколько потоков , где каждый поток может выполняться независимо, но не обязательно одновременно. Потоки могут переключаться между собой, создавая иллюзию одновременности, однако они могут работать на одном ядре процессора. Параллелизм, с другой стороны, — это выполнение нескольких задач одновременно, обычно на разных процессорах или ядрах. В контексте параллелизма, задачи действительно выполняются одновременно. 🐸 Библиотека собеса по Java #concurrency

❓ Что такое иммутабельный объект? Иммутабельный объект — это объект, состояние которого невозможно изменить после его создания.  Иммутабельность способствует безопасности потоков и предотвращению ошибок, связанных с изменениями состояния объектов. Примером может служить класс String. 🐸 Библиотека собеса по Java #core