Как использовать библиотеку Lombok
В предыдущей статье мы рассмотрели, подключить библиотеку Lombok к проекту и как установить плагин в IDE. Сегодня же мы расскажем, как использовать Lombok для уменьшения шаблонного кода при разработке программ.
Как использовать Lombok
При написании кода используются аннотации Lombok. С помощью аннатоций Lombok на этапе компиляции генерирует шаблонный код. С помощью аннотаций Lombok можно генерировать конструкторы классов, геттеры и сеттеры, методы toString, equals и hashCode. Давайте вкратце рассмотрим использование Lombok в работе.
Сеттеры и геттеры
Для генерации сеттеров и геттеров используются аннотации @Setter и @Getter, соответственно. Эти аннотации удобно навесить на POJO класс со множеством полей, дабы не генерировать шаблонный код самому.
@Getter @Setter public class Person
Здесь мы объявили класс Person с тремя полями и указали аннотации @Getter и @Setter. Если вы правильно подключили Lombok и установили плагин, то он сразу же создаст геттеры и сеттеры. Теперь можно воспользоваться созданными методами:
Person person = new Person(); person.setFirstName("Nicola"); person.setSecondName("Tesla"); person.setAddress(new Address()); System.out.println(person.getFirstName() + " " + person.getSecondName());
Примечание: если вы определите какой-либо геттер или сеттер в классе, то Lombok не будет его трогать при генерации кода. То есть уже определённые методы будут иметь приоритет над вновь создаваемыми. Также для нестатических final полей не будут сгенерированы сеттеры.
import lombok.Getter; import lombok.Setter; @Getter @Setter public class Person
public class LombokGetterSetter < public static void main(String[] args) < Person person = new Person(); person.setFirstName("Nicola"); person.setSecondName("Tesla"); person.setAddress(new Address()); System.out.println(person.getFirstName() + " " + person.getSecondName()); >>
Конструкторы
Рутинное написание типовых конструкторов можно поручить библиотеке Lombok, аннотировав нужный класс с помощью аннотаций @AllArgsConstructor, @RequiredArgsConstructor и @NoArgsConstructor. Как и следует из названий, эти аннотации приведут к генерированию таких конструкторов:
- @AllArgsConstructor – консктруктор, использующий все поля класса
- @RequiredArgsConstructor – конструктор, использующий все final поля класса
- @NoArgsConstructor – конструктор без параметров
Эти аннотации можно комбинировать между собой и использовать вместе с аннотациями @Getter и @Setter.
Давайте определим класс Person с аннотациями @NoArgsConstructor и @AllArgsConstructor:
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Person
public class ConstructorLombok < public static void main(String[] args) < Person a = new Person(); a.setFirstName("Alice"); System.out.println(a.getFirstName()); Person b = new Person("Bob", "Marley", new Address()); System.out.println(b.getFirstName()); >>
Как вы видите, Lombok сгенерировал конструктор без параметров и конструктор со всеми параметрами.
Примечание: при использовании в классе нестатических final полей невозможно использовать аннотацию @NoArgsConstructor, так как в конструкторе без параметров такие поля не будут инициализированы.
@Getter @Setter @NoArgsConstructor // эту аннотацию использовать нельзя @RequiredArgsConstructor @AllArgsConstructor public class Person
Методы toString, equals, и hashCode
Для создания метода toString воспользуйтесь аннотацией @ToString:
@Getter @Setter @ToString public class Person
public class ToStringLombok < public static void main(String[] args) < Person a = new Person(); a.setFirstName("Nicola"); a.setSecondName("Tesla"); System.out.println(a); >>
Выполнение данного кода выведет в консоль следующий текст:
Person(firstName=Nicola, secondName=Tesla, address=null)
Методы equals и hashCode генерируются с помощью аннотации @EqualsAndHashCode. Для простых классов вполне ясно и понятно использовать генерирование этих методов, но в нетривиальных случаях рекомендуется создавать equals и hashCode вручную (или средствами IDE).
Все методы воедино
Зачастую аннотации @Getter, @Setter, @ToString, @EqualsAndHashCode, и @RequiredArgsConstructor используются вместе для одного класса. Для такого типового подхода существует аннотация @Data, объединяющая все перечисленные аннотации.
С помощью аннотации @Data будут сгенерированы геттеры и сеттеры, конструктор со всеми final полями, методы toString, equals и hashCode. Эти два класса равнозначны:
@RequiredArgsConstructor @Getter @Setter @ToString @EqualsAndHashCode public class PersonA
@Data public class PersonB
Method chaining
Предположим, у нас есть класс с множеством полей. Использовать конструктор со всеми аргументами – не вариант, получится слишком длинный список аргументов. Вызывать по одному сеттеру в каждой строке может быть тоже непрактично. В этом случае можно воспользоваться аннотацией @Builder на нужном классе и использовать любой набор полей для построения объекта:
public class UserLombokExample < public static void main(String[] args) < User user = User.builder() .person(new Person()) .id(1337L) .username("alex") .build(); System.out.println(user); >>
@Builder @ToString public class User < private final Long id; private String username; private char[] password; private Person person; private Listactions; >
Начните построение объекта с вызова метода builder(), затем используйте нужные сеттеры, после чего вызовите метод build() для построения объекта.
Логгеры
Библиотеку Lombok можно использовать не только для моделей и POJO, но и для других классов – например, сервисов. Если в классе используется логгер, то генерирование этого поля можно поручить Lombok.
Например, вместо данного кода:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogLombok < private static final Logger LOG = LoggerFactory.getLogger(LogLombok.class); public static void main(String[] args) < LOG.info("Just test"); >>
Можно написать следующий код, используя @Slf4j:
import lombok.extern.java.Log; @Slf4j public class LogLombok2 < public static void main(String[] args) < log.info("Just test"); >>
В аннотированном классе будет создано такое final поле с именем log.
Помимо @Slf4j, в Lombok есть ещё аннотации @Log и @CommonsLog. Эти аннотации отвечают за генерацию переменных следующих типов:
- @Log – java.util.logging.Logger
- @Slf4j – org.slf4j.Logger
- @CommonsLog – org.apache.commons.logging.Log
NonNull
Если пометить поле аннотацией @NonNull, то в случае, если будет попытка присвоить данному полю значение null, Lombok выбросит исключение:
import lombok.NonNull; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class StrictUser
public class NonNullLombok < public static void main(String[] args) < StrictUser user = new StrictUser(null); // NullPointerException >>
Такое поведение будет аналогично тому, если бы мы написали в начале конструктора или сеттера проверку на null:
public StrictUser(@NonNull Long id)
Переменные @var и константы @val
В Lombok есть интересные аннотации @var для обозначения «изменяемых» переменных и @val для констант. Обе эти аннотации применяются для обозначения локальных переменных.
Начиная с Java 10, синтаксис языка позволяет делать то же самое. Можно использовать val для объявления локальной константы и var для объявления локальной переменной. Особенностью данных двух ключевых слов является то, что тип переменной (или константы) будет определён компилятором автоматически. То есть не потребуется указывать тип переменной (константы) вручную:
import lombok.val; import lombok.var; public class ValVarLombok < public static void main(String[] args) < val pi = 3.1415926; var speed = 100; pi = 4; // ошибка компиляции speed = 240; >>
Данные аннотации можно использовать и в «классическом» стиле:
Lombok @Getter и @Setter — больше не нужно писать геттеры и сеттеры
Вы можете добавить аннотацию @Getter и/или @Setter к любому полю, чтобы lombok автоматически сгенерировал методы получения и установки значения.
Метод получения значения по умолчанию просто возвращает значение поля и имеет имя getFoo, если поле имеет имя foo (или isFoo, если поле логического типа). Метод установки нового значения по умолчанию имеет имя setFoo, если поле имеет имя foo, возвращает void, и имеет один параметр с тем же типом, что и само поле. Этот метод просто устанавливает значение в поле.
Сгенерированные методы получения/установки значения имеют модификатор доступа public, если вы не укажете явно AccessLevel, как показано в примере ниже. Доступные уровни доступа: PUBLIC, PROTECTED, PACKAGE и PRIVATE.
Вы также можете указать аннотацию @Getter и/или @Setter для класса. В этом случае это будет так же, как будто вы указали эти аннотации для всех нестатических полей класса.
Вы можете также вручную запретить генерацию метода получения/установки для любого поля с помощью AccessLevel.NONE. Это позволяет вам переопределить поведение аннотаций @Getter, @Setter или @Data для класса.
Чтобы добавить аннотации к сгенерированному методу, используйте onMethod = @__ ( < @AnnotationsHere >) ; . Чтобы добавить аннотации только к параметру сгенерированного метода установки значения, используйте onParam = @__ ( < @AnnotationsHere >) . Но будьте осторожны! Это экспериментальная возможность.
НОВОЕ в v1.12.0: javadoc у поля теперь копируется на сгенерированные методы получения и установки значений. Обычно весь текст копируется, @return перемещается в метод получения значения, а строки @param перемещаются в метод установки значения. Перемещаются означает, что удаляются из JavaDoc поля. Также возможно определить уникальный текст для метода получения значения и метода установки значения. Для этого создайте секцию GETTER и/или SETTER. Секция — это линия в javadoc, содержащая два или более минуса (дефиса), затем текст «GETTER» или «SETTER», затем два или более минуса (дефиса) и больше ничего в линии.Если вы используете секции, то @return и @param больше не разделяются (переместите @return или @param внутрь секции).
С помощью Lombok