Lombok – це заснована на анотаціях бібліотека Java, що дозволяє скоротити написання шаблонного коду. Lombok пропонує різноманітні анотації, мета котрих замінити зайвий повторюваний код.
Наприклад, Lombok позбавляє від написання конструкторів, методів toString(), equals() і hashCode(), замість цього потрібно просто додати кілька анотацій. Також ця бібліотека інтегрується з IDE, завдяки чому робота сприймається так, наче ви написали весь шаблонний код самі.
Додавання Lombok в проект
Для підключення Lombok до проекту побудованому на maven, потрібно додати залежність до pom файлу:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>Крім того, додати залежність Lombok до конфігураційного розділу maven-compiler-plugin наступним чином:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>Налаштування Lombok в IntelliJ IDEA
Для інтеграції бібліотеки Lombok в середу розробки IntelliJ IDEA, потрібно встановити та активувати плагін Lombok:

Ще один крок, перейти в розділ налаштувань за шляхом:
Settings | Build, Execution, Deployment | Compiler | Annotation Processors
Та активувати наступні налаштування:

Тепер можна переходити до прикладів використання анотацій Lombok.
Анотації @Getter та @Setter
Можна анотувати будь-яке поле за допомогою @Getter та/або @Setter, щоб дозволити lombok автоматично генерувати геттер/сеттер за замовчуванням для цього поля.
- @Getter – для поля, що має назву (наприклад value) буде згенеровано метод getValue() (або isValue(), якщо поле має тип boolean), та за замовчуванням просто повертає значення поля
- @Setter – для поля, що має назву (наприклад value) буде згенеровано метод setValue(), котрий приймає один параметр того самого типу, що й поле, та встановлює це значення для поля
Також анотаціями @Getter та/або @Setter можна позначити весь клас. В такому випадку, ці анотації буде застосовано до всіх нестатичних полів в цьому класі.
Згенеровані методи getter/setter будуть мати модифікатор доступу public. Є можливість явно вказати рівень доступу за допомогою AccessLevel, як показано в прикладі нижче. Наявні рівні доступу: PUBLIC, PROTECTED, PACKAGE та PRIVATE.
Оголошення класу з використанням анотацій @Getter та @Setter на рівні класу:
@Getter
@Setter
public class Person {
private String fullName;
private int age;
@Setter(AccessLevel.PROTECTED)
private boolean active;
}Слід звернути увагу, що до поля active для прикладу застосовано анотацію @Setter з AccessLevel.PROTECTED (згенерований метод setActive буде мати модифікатор доступу protected).
Приклад використання класу Person:
public class Main {
public static void main(String[] args) {
var person = new Person();
person.setFullName("Тарас Очерет");
person.setActive(true);
System.out.println(person.getFullName());
System.out.println(person.isActive());
}
}Клас Person оголошений звичайним способом без використання Lombok:
public class Person {
private String fullName;
private int age;
private boolean active;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isActive() {
return active;
}
protected void setActive(boolean active) {
this.active = active;
}
}Анотації @NoArgsConstructor та @AllArgsConstructor
Ці анотації застосовуються на рівні класу, та відповідають за генерацію конструкторів:
- @NoArgsConstructor – створить конструктор без параметрів
- @AllArgsConstructor – створить конструктор, що містить по одному параметру для кожного поля в класі
Оголошення класу з використанням Lombok анотацій @NoArgsConstructor та @AllArgsConstructor:
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String fullName;
private int age;
private boolean active;
}Оголошення класу класичним способом без використання Lombok:
public class Person {
private String fullName;
private int age;
private boolean active;
public Person() {}
public Person(String fullName, int age, boolean active) {
this.fullName = fullName;
this.age = age;
this.active = active;
}
}Анотація @RequiredArgsConstructor
@RequiredArgsConstructor – генерує конструктор з одним параметром для кожного поля, яке вимагає спеціальної обробки, а саме:
- усі неініційовані final поля
- будь-які поля, позначені як @NonNull та неініційовані в місці оголошення
Для полів, позначених @NonNull, також генерується явна перевірка на null. Конструктор створить виняток NullPointerException, якщо будь-який з параметрів, призначених для полів позначених @NonNull, містить значення null. Порядок параметрів відповідає порядку оголошення полів у класі.
Оголошення класу з використанням Lombok анотацій @RequiredArgsConstructor та @NonNull:
@RequiredArgsConstructor
public class Person {
@NonNull private String fullName;
private final int age;
private boolean active;
}Оголошення класу класичним способом без використання Lombok:
public class Person {
private String fullName;
private final int age;
private boolean active;
public Person(String fullName, int age) {
if(fullName == null) {
throw new NullPointerException("fullName can not be null");
}
this.fullName = fullName;
this.age = age;
}
}Також слід додати, що анотації @NoArgsConstructor, @AllArgsConstructor та @RequiredArgsConstructor під час генерації конструкторів ігнорують статичні поля.
Кожна з цих анотацій для генерації конструкторів, допускає альтернативну форму, де згенерований конструктор є приватним, і генерується додатковий статичний фабричний метод, який обгортає приватний конструктор. Цей режим активується шляхом надання значення атрибуту staticName анотації, наприклад: @AllArgsConstructor(staticName=”of”):
@AllArgsConstructor(staticName = "of")
@ToString
public class Person {
private String fullName;
private int age;
private boolean active;
}Протестую клас Person:
public class Main {
public static void main(String[] args) {
Person person = Person.of("Тарас Чубай", 30, true);
System.out.println(person.toString());
}
}Тепер аналог класу зі статичним фабричним методом без використання Lombok:
public class Person {
private String fullName;
private int age;
private boolean active;
private Person(String fullName, int age, boolean active) {
this.fullName = fullName;
this.age = age;
this.active = active;
}
public static Person of(String fullName, int age, boolean active) {
return new Person(fullName, age, active);
}
@Override
public String toString() {
return "Person{" +
"fullName='" + fullName + '\'' +
", age=" + age +
", active=" + active +
'}';
}
}Анотація @ToString
Якщо клас анотовано @ToString, Lombok згенерує для нього метод toString() (докладніше Java – метод toString()). За замовчуванням буде повертатися рядок, що містить ім’я класу, за яким слідує перелік не статичних полів класу, у форматі ім’я=значення, розділених комами:
@AllArgsConstructor
@ToString
public class Person {
private String fullName;
private int age;
private boolean active;
}
public class Main {
public static void main(String[] args) {
var person = new Person("Валентин Опенько", 30, false);
System.out.println(person);
}
}
// Результат: Person(fullName=Валентин Опенько, age=30, active=false)Додавши до анотації @ToString параметр includeFieldNames=false, з результуючого рядка будуть виключені імена полів:
@AllArgsConstructor
@ToString(includeFieldNames = false)
public class Person {
private String fullName;
private int age;
private boolean active;
}
public class Main {
public static void main(String[] args) {
var person = new Person("Валентин Опенько", 30, false);
System.out.println(person);
}
}
// Результат: Person(Валентин Опенько, 30, false)За замовчуванням при генерації методу toString() враховуються всі нестатичні поля класу. Якщо потрібно, щоб Lombok проігнорував окреме поле, можна анотувати його @ToString.Exclude:
@AllArgsConstructor
@ToString
public class Person {
private String fullName;
private int age;
@ToString.Exclude private boolean active;
}
// Результат: Person(fullName=Валентин Опенько, age=30)Як варіант, можна самостійно вказати поля, котрі повинні повертатися методом toString(). Для цього потрібно анотувати клас @ToString(onlyExplicitlyIncluded=true), після чого позначити @ToString.Include кожне поле, яке слід включити в рядок:
@AllArgsConstructor
@ToString(onlyExplicitlyIncluded = true)
public class Person {
@ToString.Include private String fullName;
@ToString.Include private int age;
private boolean active;
}
// Результат: Person(fullName=Валентин Опенько, age=30)Анотація @EqualsAndHashCode
Для класу анотованого @EqualsAndHashCode, Lombok автоматично реалізує методи equals() та hashCode(). За замовчуванням враховуватимуться всі нестатичні поля класу.
Можна вплинути на те, які поля не будуть використовуватися, анотувавши їх @EqualsAndHashCode.Exclude:
@AllArgsConstructor
@EqualsAndHashCode
public class Person {
@EqualsAndHashCode.Exclude private int id;
private String fullName;
private int age;
private boolean active;
}Як варіант, можна анотувати клас за допомогою @EqualsAndHashCode(onlyExplicitlyIncluded = true), а потім точно вказати, які поля слід використовувати, позначивши їх @EqualsAndHashCode.Include:
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Person {
private int id;
@EqualsAndHashCode.Include private String fullName;
@EqualsAndHashCode.Include private int age;
private boolean active;
}Оголошення класу з методами equals() та hashCode() класичним способом, без використання Lombok:
public class Person {
private int id;
private String fullName;
private int age;
private boolean active;
public Person(int id, String fullName, int age, boolean active) {
this.id = id;
this.fullName = fullName;
this.age = age;
this.active = active;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person person)) return false;
if (age != person.age) return false;
if (active != person.active) return false;
return fullName.equals(person.fullName);
}
@Override
public int hashCode() {
int result = fullName.hashCode();
result = 31 * result + age;
result = 31 * result + (active ? 1 : 0);
return result;
}
}Анотація @Data
@Data – це скорочена анотація, що поєднує в собі можливості @Getter, @Setter, @RequiredArgsConstructor, @ToString та @EqualsAndHashCode. Таким чином, @Data генерує весь шаблонний код, залучений до роботи з об’єктами POJO (Plain Old Java Objects):
@Data
public class Person {
private String fullName;
private int age;
private boolean active;
}Анотація @Value
@Value – це незмінний варіант @Data. З цією анотацією, Lombok за замовчуванням робить всі поля private та final. Крім того, сеттери не генеруються, а клас позначається як final. Таким чином, від цього класу не можна успадковуватись. Так само як і у випадку з @Data, створюються реалізації toString(), equals() і hashCode():
@Value
public class Person {
String fullName;
int age;
boolean active;
}Анотація @Builder
Використовується при потребі створити об’єкт builder, який дозволяє створювати об’єкти, дотримуючись покрокової процедури, наприклад:
Person person = Person.builder().fullName("Валентин Дуць").age("Maria").active(true).build();Це особливо корисно, під час роботи з великими класами, що містять кілька полів і більше. Замість використання конструктора з багатьма полями, можна спробувати цей підхід. При використанні анотації @Builder, Lombok генерує клас, що реалізує шаблон програмування builder:
@Builder
@ToString
public class Person {
private String fullName;
private int age;
private boolean active;
}
public class Main {
public static void main(String[] args) {
Person person = Person.builder()
.fullName("Роман Гринь")
.age(27)
.active(false)
.build();
System.out.println(person);
}
}
// Результат: Person(fullName=Роман Гринь, age=27, active=false)Документація проекту Lombok доступна за посиланням: