Что такое ленивая загрузка (Lazy Loading) в программировании?

«Что такое ленивая загрузка (Lazy Loading) в программировании?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ленивая загрузка (Lazy Loading) — это паттерн отложенной инициализации, при котором ресурсоёмкий объект или данные создаются/загружаются не в момент создания родительского объекта, а только при первом обращении к ним.

Цель: оптимизация производительности и потребления памяти за счёт загрузки только необходимых в данный момент ресурсов.

Ключевой принцип: "Не делай работу, пока в ней нет необходимости".

Пример реализации на Java с Supplier:

public class Lazy<T> {
    private Supplier<T> supplier;
    private T value;
    private volatile boolean initialized = false; // для потокобезопасности

    public Lazy(Supplier<T> supplier) {
        this.supplier = supplier;
    }

    public T get() {
        if (!initialized) {
            synchronized (this) {
                if (!initialized) { // Double-checked locking
                    value = supplier.get(); // Дорогая операция выполняется здесь
                    initialized = true;
                }
            }
        }
        return value;
    }
}

// Использование
Lazy<ExpensiveObject> lazyResource = new Lazy<>(() -> {
    System.out.println("Creating expensive object...");
    return new ExpensiveObject(); // Создание происходит только при первом get()
});

// Объект ExpensiveObject ещё не создан
ExpensiveObject obj = lazyResource.get(); // Создание происходит сейчас
ExpensiveObject obj2 = lazyResource.get(); // Возвращается уже созданный объект

Типичные примеры применения:

  • ORM (Hibernate/JPA): Загрузка связанных коллекций (@OneToMany(fetch = FetchType.LAZY)). Коллекция загружается только при явном обращении к getItems().
  • Загрузка ресурсов: Изображения на веб-странице загружаются по мере прокрутки (lazy load images).
  • Создание тяжёлых объектов: Конфигурации, подключения к БД, которые могут не понадобиться.

Альтернатива: Eager Loading (жадная загрузка), когда все связанные данные загружаются сразу.