Вопрос 21 · Раздел 13

Почему LocalDate, LocalDateTime иммутабельны?

Классы LocalDate, LocalTime, LocalDateTime (Java 8+) нельзя изменить после создания. Вместо изменения они возвращают новые объекты.

Версии по языкам: English Russian Ukrainian

Junior Level

Классы LocalDate, LocalTime, LocalDateTime (Java 8+) нельзя изменить после создания. Вместо изменения они возвращают новые объекты.

LocalDate date = LocalDate.of(2024, 1, 1);
date.plusDays(1);         // date не изменился!
LocalDate next = date.plusDays(1); // новый объект — нужно присвоить

Почему так сделали?

  1. Потокобезопасность — можно использовать в любом потоке без синхронизации
  2. Безопасность — метод не может случайно изменить вашу дату
  3. Удобство — методы можно chaining’ить: date.plusMonths(1).withDayOfMonth(10)

Старый Date был мутабельным — и это проблема

Date date = new Date();
date.setYear(120); // Опасно! Меняет объект
// Баг: мутабельный Date меняется внутри метода
void process(Date d) { d.setTime(d.getTime() + 86400000); } // сломал объект у вызывающего!
// LocalDate.plusDays() возвращает новый объект — оригинал не тронут.

Middle Level

Исправление проблем java.util.Date

java.util.Date был мутабельным, что приводило к:

  • Утечкам через ссылки — передали дату в метод, а он её изменил
  • Проблемам в многопоточности — нужна внешняя синхронизация

Преимущества LocalDate

Потокобезопасность: можно хранить в статических константах, делить между потоками.

Целостность Domain Model: если у заказа есть дата создания, она не изменится случайным вызовом.

Кэшируемость: идеально как ключи в HashMap.

Fluent API

LocalDate date = LocalDate.now()
    .plusMonths(1)
    .withDayOfMonth(10)
    .minusDays(3);
// Каждый вызов возвращает НОВЫЙ объект

Все классы java.time иммутабельны

  • LocalDate, LocalTime, LocalDateTime
  • Instant, Duration, Period
  • ZonedDateTime, OffsetDateTime

Когда иммутабельность LocalDate имеет цену

В высоконагруженных системах с миллионами временных меток в секунду, каждый plusXxx() создаёт новый объект — GC pressure.


Senior Level

Value-Based Classes

LocalDate и другие классы java.time — это Value-Based Classes. Они:

  • Иммутабельны
  • Сравниваются по значению (equals), а не по ссылке
  • Могут кешироваться и переиспользоваться JVM
  • Не имеют публичных конструкторов (фабричные методы of(), now())

Память и производительность

Объекты LocalDate очень маленькие (хранят только int поля: year, month, day). Создание новых объектов:

  • Минимальный overhead — 3 int поля + header
  • Современные JVM эффективно справляются с короткоживущими объектами
  • Безопасность стоит дороже незначительного overhead по памяти

Резюме для Senior

  • Иммутабельность в java.time — гарантия безопасности и предсказуемости
  • Исправление фундаментальных недостатков java.util.Date
  • Value-Based Classes — стандарт для современной Java
  • Все методы возвращают новые объекты — chaining без побочных эффектов

🎯 Шпаргалка для интервью

Обязательно знать:

  • LocalDate, LocalTime, LocalDateTime — иммутабельны, каждый метод возвращает НОВЫЙ объект
  • Исправление проблем java.util.Date (мутабельный, утечки через ссылки, проблемы в многопоточности)
  • Fluent API: date.plusMonths(1).withDayOfMonth(10) — chaining без побочных эффектов
  • Потокобезопасность: можно хранить в static константах, делить между потоками
  • Value-Based Classes: иммутабельны, сравниваются по значению, могут кешироваться JVM
  • Все java.time классы иммутабельны: Instant, Duration, Period, ZonedDateTime

Частые уточняющие вопросы:

  • Почему LocalDate не изменяет себя? — Чтобы избежать побочных эффектов и обеспечить потокобезопасность
  • Что такое Value-Based Classes? — Иммутабельные классы, сравниваются по equals, могут кешироваться, нет публичных конструкторов
  • Есть ли цена иммутабельности LocalDate? — GC pressure при миллионах временных меток/сек — каждый plusXxx() = новый объект
  • LocalDate vs Date? — Date мутабельный и устарел; LocalDate иммутабельный и безопасный

Красные флаги (НЕ говорить):

  • «date.plusDays(1) меняет дату» — возвращает НОВЫЙ объект, оригинал не меняется
  • «LocalDate нужно синхронизировать» — потокобезопасен по умолчанию
  • «java.util.Date — хороший выбор» — мутабельный, устарел, используйте java.time
  • «LocalDate имеет публичный конструктор» — нет, фабричные методы of(), now()

Связанные темы:

  • [[1. Что такое иммутабельный (неизменяемый) объект]]
  • [[2. Какие преимущества даёт использование иммутабельных объектов]]
  • [[6. Почему иммутабельные объекты thread-safe]]
  • [[23. Как иммутабельность влияет на производительность]]