Питання 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. Зручність — методи можна чейнити: 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. Що таке незмінний (immutability) об’єкт]]
  • [[2. Які переваги дає використання незмінних об’єктів]]
  • [[6. Чому незмінні об’єкти thread-safe]]
  • [[23. Як незмінність впливає на продуктивність]]