← Назад к вопросам

Где применяется Supplier?

2.0 Middle🔥 191 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Где применяется Supplier в Java?

Определение Supplier

Supplier<T> — это функциональный интерфейс, который не принимает аргументов и возвращает значение типа T.

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

Supplier — это поставщик/производитель значений.

1. Ленивая инициализация (Lazy Initialization)

public class DatabaseService {
    public void executeQuery(Supplier<PreparedStatement> stmtSupplier) {
        PreparedStatement stmt = stmtSupplier.get(); // Создаётся только здесь
        stmt.executeQuery();
    }
}

DatabaseService service = new DatabaseService();
service.executeQuery(() -> connection.prepareStatement("SELECT * FROM users"));

2. Default Values в Optional

public Optional<User> findById(Long id) {
    return Optional.empty();
}

// Supplier для значения по умолчанию
public User getUserWithFallback(Long id) {
    return findById(id).orElseGet(() -> new User("Guest", "guest@example.com"));
}

// Функция вызовется ТОЛЬКО если пользователя нет
public User getUserOrDefault(Long id) {
    return findById(id).orElseGet(this::getDefaultUser);
}

3. Factory Pattern

public class ConnectionFactory {
    public Supplier<Connection> createConnectionSupplier() {
        return () -> {
            System.out.println("Создаём новое подключение...");
            return DriverManager.getConnection(url, username, password);
        };
    }
}

Supplier<Connection> connSupplier = factory.createConnectionSupplier();
Connection conn1 = connSupplier.get(); // Creates new connection
Connection conn2 = connSupplier.get(); // Creates another

4. Dependency Injection в Spring

@Component
public class UserService {
    private final Supplier<UserRepository> repoSupplier;
    
    @Autowired
    public UserService(Supplier<UserRepository> repoSupplier) {
        this.repoSupplier = repoSupplier;
    }
    
    public void processUsers() {
        UserRepository repo = repoSupplier.get();
        List<User> users = repo.findAll();
    }
}

Spring автоматически внедрит Supplier<UserRepository>. Это избегает circular dependencies.

5. Функциональное программирование (Streams)

// Генерируем 10 случайных чисел
Supplier<Integer> randomSupplier = () -> (int) (Math.random() * 100);
Stream<Integer> randomNumbers = Stream.generate(randomSupplier).limit(10);

// Генерируем UUID
Supplier<String> uuidSupplier = () -> UUID.randomUUID().toString();
List<String> ids = Stream.generate(uuidSupplier).limit(5).collect(Collectors.toList());

// Генерируем объекты
Supplier<User> userSupplier = () -> new User("User" + System.nanoTime(), "user@example.com");
List<User> users = Stream.generate(userSupplier).limit(3).collect(Collectors.toList());

6. Кэширование и Memoization

public class CachedSupplier<T> implements Supplier<T> {
    private final Supplier<T> supplier;
    private T cachedValue;
    private boolean initialized = false;
    
    @Override
    public synchronized T get() {
        if (!initialized) {
            cachedValue = supplier.get();
            initialized = true;
        }
        return cachedValue;
    }
}

Supplier<ExpensiveObject> supplier = new CachedSupplier<>(() -> new ExpensiveObject());
ExpensiveObject obj1 = supplier.get(); // создаёт
ExpensiveObject obj2 = supplier.get(); // из кэша

7. Логирование дорогостоящих операций

public void log(Supplier<String> messageSupplier) {
    if (isDebugEnabled()) {
        System.out.println(messageSupplier.get());
    }
}

// Вычисление выполнится только если debug enabled
logger.log(() -> {
    List<String> items = expensiveOperation();
    return "Результат: " + items.size();
});

8. Обработка исключений

public static <T> T getOrNull(Supplier<T> supplier) {
    try {
        return supplier.get();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

String value = getOrNull(() -> riskyOperation());

Сравнение функциональных интерфейсов

ИнтерфейсАргументыВозвратПример
Supplier<T>НЕТTпоставщик
Consumer<T>Tvoidпечать
Function<T,R>TRпреобразование
Predicate<T>Tbooleanпроверка

Главные применения

  1. Ленивая инициализация - дорогостоящие объекты создаются только когда нужны
  2. Factory pattern - создание объектов по требованию
  3. Значения по умолчанию в Optional.orElseGet()
  4. Dependency Injection - внедрение зависимостей в Spring
  5. Stream.generate() - генерация потоков
  6. Кэширование - ленивое кэширование значений
  7. Логирование - вычисление только при необходимости

Главное преимущество: Вычисление откладывается до момента, когда значение действительно нужно.

Где применяется Supplier? | PrepBro