Как использовать библиотеку Lombok
[Как использовать библиотеку Lombok]
В предыдущей статье мы рассмотрели, подключить библиотеку Lombok к проекту и как установить плагин в IDE. Сегодня же мы расскажем, как использовать Lombok для уменьшения шаблонного кода при разработке программ.
Как использовать Lombok
При написании кода используются аннотации Lombok. С помощью аннатоций Lombok на этапе компиляции генерирует шаблонный код. С помощью аннотаций Lombok можно генерировать конструкторы классов, геттеры и сеттеры, методы toString, equals и hashCode. Давайте вкратце рассмотрим использование Lombok в работе.
Сеттеры и геттеры
Для генерации сеттеров и геттеров используются аннотации @Setter и @Getter, соответственно. Эти аннотации удобно навесить на POJO класс со множеством полей, дабы не генерировать шаблонный код самому.
@Getter
@Setter
public class Person {
private String firstName;
private String secondName;
private Address address;
}
Здесь мы объявили класс 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 {
private String firstName;
private String secondName;
private Address address;
}
public class Address {
}
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 {
private String firstName;
private String secondName;
private Address address;
}
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 {
private final String firstName;
private String secondName;
private Address address;
}
Методы toString, equals, и hashCode
Для создания метода toString воспользуйтесь аннотацией @ToString:
@Getter
@Setter
@ToString
public class Person {
private String firstName;
private String secondName;
private Address address;
}
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 {
private String firstName;
private String secondName;
private Address address;
}
@Data
public class PersonB {
private String firstName;
private String secondName;
private Address address;
}
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 List<String> actions;
}
Начните построение объекта с вызова метода 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 {
@NonNull
private final Long id;
private String username;
}
public class NonNullLombok {
public static void main(String[] args) {
StrictUser user = new StrictUser(null); // NullPointerException
}
}
Такое поведение будет аналогично тому, если бы мы написали в начале конструктора или сеттера проверку на null:
public StrictUser(@NonNull Long id) {
Objects.requireNonNull(id);
this.id = 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;
}
}
Данные аннотации можно использовать и в «классическом» стиле:
import lombok.val;
import lombok.var;
public class ValVarLombok2 {
public static void main(String[] args) {
@val double pi = 3.1415926;
@var double speed = 100;
System.out.println("pi=" + pi);
System.out.println("speed=" + speed);
pi = 4;
speed = 240;
System.out.println("pi=" + pi);
System.out.println("speed=" + speed);
}
}
В этом случае ошибки компиляции не будет, но значение константы не изменится при попытке её переопределить.
Заключение
В данной статье мы рассказали о ключевых возможностях библиотеки Lombok. С помощью Lombok вы можете упростить и ускорить ращработку программ, используя аннотации длягенерирования конструкторов (@AllArgsConstructor, @RequiredArgsConstructor и @NoArgsConstructor), геттеров и сеттеров (@Getter, @Setter), генерировать стандартные методы (@ToString, @EqualsAndHashCode), генерировать поле для логгера (@Log, @Slf4j, @CommonsLog), использовать функциональность val и var в версиях ниже Java 10. Дерзайте!
Как использовать библиотеку Lombok
Комментарии 0