💿 Java Records: Конец эпохи Lombok?
Долгие годы Project Lombok был нашим единственным спасением от бесконечных геттеров, сеттеров,
Многие поспешили удалить Lombok и переписать всё на рекорды. И... столкнулись с проблемами. Давайте разберем, почему
🏎 Скорость написания
Lombok (
Record:
Тут победа за рекордами. Синтаксис максимально лаконичен. Мы объявляем состояние, а не поля.
🔍 Что под капотом? (Главные отличия)
Вот здесь начинаются нюансы, из-за которых Records нельзя назвать полной заменой Lombok.
1. Жесткая неизменяемость (Immutability)
Record - это всегда
2. Запрет на наследование
Рекорды не могут наследоваться от других классов (они уже неявно наследуются от
• Если у вас есть
3. Имена геттеров
Это ломает многие старые библиотеки.
• Lombok/JavaBean:
• Record:
• Совет: Jackson и современные JSON-библиотеки уже умеют с этим работать, но легаси-фреймворки могут "не увидеть" ваши поля.
✨ Killer Feature: Компактные конструкторы
То, чего нет в Lombok. Валидация данных в рекордах выглядит потрясающе чисто. Вам не нужно дублировать аргументы:
🏆 Вердикт: Кто победил?
Никто. Это инструменты для разных целей.
✅ Используйте record: Для DTO, ключей в Map, ответов API, записей в Event Log и промежуточных данных в Stream API. Это "именованные кортежи" данных.
✅ Используйте Lombok / POJO: Для JPA сущностей (Hibernate не очень любит рекорды из-за прокси и отсутствия сеттеров), для классов с наследованием и там, где нужна мутабельность.
#Java #Lombok #CleanCode #Java17
👉 @java_geek
Долгие годы Project Lombok был нашим единственным спасением от бесконечных геттеров, сеттеров,
equals() и hashCode(). Но начиная с Java 14 (и официально в Java 16), в языке появилась нативная альтернатива - Records.Многие поспешили удалить Lombok и переписать всё на рекорды. И... столкнулись с проблемами. Давайте разберем, почему
record - это не просто "короткий класс".🏎 Скорость написания
Lombok (
@Value для неизменяемости):
@Value
public class User {
String name;
int age;
}
Record:
public record User(String name, int age) {}
Тут победа за рекордами. Синтаксис максимально лаконичен. Мы объявляем состояние, а не поля.
🔍 Что под капотом? (Главные отличия)
Вот здесь начинаются нюансы, из-за которых Records нельзя назвать полной заменой Lombok.
1. Жесткая неизменяемость (Immutability)
Record - это всегда
final класс с final полями. Вы не можете сделать "сеттер" в рекорде. Если вам нужен изменяемый DTO (например, для заполнения формы по шагам) - Record не подойдет. Lombok @Data всё еще нужен.2. Запрет на наследование
Рекорды не могут наследоваться от других классов (они уже неявно наследуются от
java.lang.Record).• Если у вас есть
BaseEntity с полем ID - вы не сможете унаследовать рекорд от него.3. Имена геттеров
Это ломает многие старые библиотеки.
• Lombok/JavaBean:
getName(), getAge()• Record:
name(), age()• Совет: Jackson и современные JSON-библиотеки уже умеют с этим работать, но легаси-фреймворки могут "не увидеть" ваши поля.
✨ Killer Feature: Компактные конструкторы
То, чего нет в Lombok. Валидация данных в рекордах выглядит потрясающе чисто. Вам не нужно дублировать аргументы:
public record User(String name, int age) {
// Обратите внимание: нет скобок с аргументами!
public User {
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
name = name.toUpperCase(); // Можно даже менять данные перед записью
}
}
🏆 Вердикт: Кто победил?
Никто. Это инструменты для разных целей.
✅ Используйте record: Для DTO, ключей в Map, ответов API, записей в Event Log и промежуточных данных в Stream API. Это "именованные кортежи" данных.
✅ Используйте Lombok / POJO: Для JPA сущностей (Hibernate не очень любит рекорды из-за прокси и отсутствия сеттеров), для классов с наследованием и там, где нужна мутабельность.
#Java #Lombok #CleanCode #Java17
👉 @java_geek
👍2❤1🔥1
🔒 Java Sealed Classes: Диктатура в вашей иерархии
Раньше в Java у нас было всего два стула для классов:
1. Public: Наследуйся кто хочет (открытый проходной двор).
2. Final: Никто не пройдет (полная изоляция).
Но что, если я хочу разрешить наследование только моим классам
Начиная с Java 17, у нас есть Sealed Classes.
🚧 Как это работает?
Вы используете ключевое слово
Теперь компилятор гарантирует: в мире существуют только три вида
🤝 Идеальная пара: Sealed + Records
Чаще всего наследниками делают
🧠 Главная фишка: Умный Switch (Pattern Matching)
Зачем нам эти ограничения? Ради исчерпываемости (Exhaustiveness).
Когда вы используете
Вам не нужно писать
В чем магия? Если через полгода вы добавите в
📜 Три правила для наследников
Наследник
1.
2.
3.
🚀 Итог: Используйте Sealed Classes, когда ваша модель данных представляет собой конечное множество вариантов:
🔴 Статусы заказа
🔴 Типы пользователей (Admin, User, Guest)
🔴 Результаты операций (Success, Error)
Это делает код предсказуемым и безопасным на уровне компилятора.
#Java17 #Architecture #CleanCode #PatternMatching
👉 @java_geek
Раньше в Java у нас было всего два стула для классов:
1. Public: Наследуйся кто хочет (открытый проходной двор).
2. Final: Никто не пройдет (полная изоляция).
Но что, если я хочу разрешить наследование только моим классам
Circle и Square, но запретить Васе из соседнего отдела создавать свой кривой Triangle?Начиная с Java 17, у нас есть Sealed Classes.
🚧 Как это работает?
Вы используете ключевое слово
sealed и permits, чтобы явно перечислить, кому дозволено быть вашим наследником.
public sealed interface PaymentResult
permits Success, Failure, Pending {
}
Теперь компилятор гарантирует: в мире существуют только три вида
PaymentResult. Четвертого не дано.🤝 Идеальная пара: Sealed + Records
Чаще всего наследниками делают
record, потому что они идеально подходят для хранения данных.
public record Success(String txId) implements PaymentResult {}
public record Failure(String error) implements PaymentResult {}
public record Pending(long timestamp) implements PaymentResult {}
🧠 Главная фишка: Умный Switch (Pattern Matching)
Зачем нам эти ограничения? Ради исчерпываемости (Exhaustiveness).
Когда вы используете
sealed классы в новых switch (Java 21+), компилятор знает все возможные варианты.Вам не нужно писать
default ветку!
String message = switch (result) {
case Success s -> "Paid! ID: " + s.txId();
case Failure f -> "Error: " + f.error();
case Pending p -> "Wait...";
// Нет default! И это безопасно.
};
В чем магия? Если через полгода вы добавите в
permits новый вариант Cancelled, ваш код перестанет компилироваться везде, где используется этот switch. Компилятор ткнет вас носом: "Ты забыл обработать новый статус!". Это спасает от сотен багов в сложной бизнес-логике.📜 Три правила для наследников
Наследник
sealed класса обязан выбрать одну из трех стратегий:1.
final: На мне иерархия заканчивается (как в Records).2.
sealed: Я продолжаю жесткий контроль, вот мои наследники.3.
non-sealed: Я открываю шлюзы - от меня может наследоваться кто угодно (возврат к старому поведению).🚀 Итог: Используйте Sealed Classes, когда ваша модель данных представляет собой конечное множество вариантов:
Это делает код предсказуемым и безопасным на уровне компилятора.
#Java17 #Architecture #CleanCode #PatternMatching
👉 @java_geek
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2