Lombok getter/setter против записи Java 14

Мне нравится проект Lombok, но сейчас я читаю и пробую некоторые новые функции java 14.

Внутри новой возможности есть ключевое слово record, которое позволяет создать класс с уже встроенными следующими функциями: конструктор, закрытые конечные поля, методы доступа, equals/hashCode, методы получения, toString.

Теперь мой вопрос: лучше полагаться на функцию Lombok или мы должны начать использовать функцию записи:

Лучше использовать это:

record Person (String name, String surname) {}

или это:

@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class GetterSetterExample {
  @Getter private int name;
  @Getter private int surname;
}

Каковы плюсы и минусы обоих подходов?

7 ответов

Решение

Ломбок и recordОсобенностью языка Java являются разные инструменты для разных вещей. Есть некоторое поверхностное совпадение, но не позволяйте этому отвлекать вас.

Ломбок - это во многом синтаксическое удобство; это макропроцессор, в который предварительно загружены некоторые известные полезные шаблоны кода. Это не придает никакой семантики; он просто автоматизирует шаблоны в соответствии с некоторыми ручками, которые вы устанавливаете в коде с аннотациями. Lombok - это исключительно удобство реализации классов переноса данных.

Записи - это семантическая функция; это номинальные кортежи. Сделав семантическое объявление, чтоPoint является кортежем(int x, int y), компилятор может получить свое представление, а также протоколы построения, объявления, равенства, хеширования и строкового представления из этого описания состояния. Поскольку они несут семантику, читатели и фреймворки также могут с большей уверенностью рассуждать об API записей. (Это также может быть синтаксически удобно; если да, то отлично.)

NB: вместо этой рождественской елки аннотаций вы можете просто использовать @Valueна классе. Обратите внимание, что это делает класс окончательным и делает все поля закрытыми и окончательными, а также дает вам все остальное. Это близко к тому, что есть записи (они тоже окончательные, и все поля внутри окончательные).

recordвсе еще находится на стадии предварительного просмотра, поэтому для производственного кода он, очевидно, пока не подходит. Используйте ломбок.

Когда записи не доступны для предварительного просмотра, все становится сложнее. Ломбок НАМНОГО более гибкий; вы можете легко поменять местами какой-либо новый аспект без необходимости переписывать весь код (вы можете просто, например, добавить предложение 'extends' к своему классу, не создавая вручную методы equals и hashCode; что-то записи не могут вам дать). Lombok также дает вам больше возможностей: вы можете, например, добавить строитель, добавив@Builderаннотация; записи не могут.

Если маловероятно, что вы собираетесь использовать что-либо из этого для класса, который разрабатываете, я бы использовал записи.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я являюсь основным участником проекта Lombok.

Я тоже некоторое время экспериментировал с этой комбинацией и, немного поработав, могу перечислить следующие различия:

Ломбок

  • Записи еще не выпущены, а являются лишь функцией предварительного просмотра. Так что оставаться с Ломбоком имеет больше смысла.
  • Они пока не являются таким мощным инструментом для уничтожения Ломбока в целом. Обратите внимание, что библиотека может предложить гораздо больше, чем просто@Getter, @AllArgsConstructor, @ToString, @EqualsAndHashCode.
  • Испытанный на себе, EqualsAndHashCodeэто не то же самое, что можно было бы ожидать, когда дело доходит до перехода к записям.

Записи

  • С другой стороны, если требуется, чтобы ваше объектное представление было "носителем данных", вы все равно можете воспользоваться преимуществами Records, не полагаясь на дополнительную библиотеку, чтобы уменьшить шаблонный код для точного выполнения этого. Вот почему в этом блоге в качестве заключительного примечания читается следующее:

    Это также поможет командам избавиться от многих вручную написанных реализаций базового шаблона и уменьшить или исключить необходимость в библиотеках, таких как Lombok.

Конечно, в повседневной жизни всегда мудро, исходя из требований проекта, выбирать, какой путь следовать и как практиковаться.

Если ваш класс является "прозрачным, неглубоко неизменяемым агрегатом данных", тогда запись подойдет, потому что:

  1. в нем даже меньше церемоний, чем в классе, помеченном Ломбоком
  2. он несет семантическую информацию "это неизменный класс данных" (как подчеркивается в ответе Брайана Гетца). Эта семантическая информация может быть полезной как для программистов, так и для фреймворков.

Я бы все равно использовал Lombok, если ваш класс не может жить с ограничениями записей (например, неизменяемость, без построителя, не расширяемый).

Java Records не требует дополнительных зависимостей, поэтому я думаю, что лучше использовать их вместо Lombok.

Если ваш проект поддерживает Java 14, вы уже можете использовать их в Eclipse.

Для этого на торговой площадке есть плагин:

https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415

Я бы сказал, не очень хорошая сделка!

Просто record (Java 14) дает вам:

      @Getter/@Setter
@AllArgsConstructor
@ToString
@EqualsAndHashCode (Not Exactly)

В обмен на (особенности Ломбока )

      @NonNull    
@Cleanup    
@Getter/@Setter    
@ToString    
@EqualsAndHashCode    
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor    
@Data    
@Value    
@Builder    
@SneakyThrows    
@Synchronized    
@With    
@Getter(lazy=true)    
@Log

Короче говоря, если вы занимаетесь функциональным кодированием на Java, используйте записи. В противном случае используйте Lombok, он намного более гибкий и мощный.

Есть некоторые исключения из этого правила, например, в кодировании API.

Другие вопросы по тегам