JavaRush /Java блог /Java Developer /Библиотека Lombok
Сергей
40 уровень
Москва

Библиотека Lombok

Статья из группы Java Developer
Библиотека Lombok сокращает количество написанного кода, улучшая читаемость. Библиотека Lombok - 1Пример использования. Обычный класс Person c тремя полями:

public class Person {

    private String name;
    private int age;
    private Cat cat;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name) &&
                Objects.equals(cat, person.cat);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, cat);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", cat=" + cat +
                '}';
    }
}
Тоже самое с lombok

@Data
public class Person {
    private String name;
    private int age;
    private Cat cat;
}
Мы убрали кучу кода, однако, все методы и модификаторы остались. Как это работает. Lombok генерирует код на этапе компиляции. Сама библиотека lombok отсутствует в рантайме. Ее использование не увеличивает размер программы. При использовании Lombok наш исходный код не будет валидным кодом Java. Поэтому потребуется установить плагин для IDE, иначе среда разработки не поймёт, с чем имеет дело. Lombok поддерживает все основные Java IDE. Интеграция бесшовная. Все функции вроде «показать использования» и «перейти к реализации» продолжают работать как и раньше, перемещая вас к соответствующему полю/классу. Итак, для простых классов можно воспользоваться аннотацией @Data. @Data - генерирует конструктор, геттеры, сеттеры, методы equals, hashCode, toString. Чтобы сделать объекты неизменяемыми есть @Value. @Value - генерирует конструктор, только геттеры, методы equals, hashCode, toString. А также делает все поля private и final.

@Value
public class Cat {
    String name;
    int age;
    Person person;
}
С неизменяемыми классами хорошо сочетаются аннотации @With и @Builder.

@With
@Builder
@Value
public class Cat {
    String name;
    int age;
    Person person;
}
Если мы хотим у неизменяемого объекта поменять поле, то нам нужно сделать клон этого объекта с одним измененным параметром. @With - добавляет методы для каждого поля, которые делают клон объекта с одним измененным полем.

 Cat anotherCat = cat.withName("Вася");
anotherCat - новый объект у которого значения полей такие же как у cat, кроме поля name. @Builder - генерирует методы, которыми мы инициализируем объект по цепочке. Это удобно когда мы не хотим использовать конструктор со всеми параметрами (Если у нас класс неизменяемый, то в нем единственный конструктор со всеми параметрами).

Cat cat = Cat.builder()
                .name("Мурка")
                .age(3)
                .person(person)
                .build();
Цикличный вызов методов Если объекты имеют двунаправленную связь, т.е. ссылки друг на друга, то использование методов toString, equals и hashCode приведет к ошибке StackOverflowError. Т.к. будет цикличный вызов методов вложенных объектов. Данный код приведет к ошибке:

public class Main {

    public static void main(String[] args) {
        Person person = new Person();

        Cat cat = Cat.builder()
                .name("Мурка")
                .age(3)
                .person(person)
                .build();

        person.setName("Иван");
        person.setAge(26);
        person.setCat(cat);

        System.out.println(person);
        System.out.println(cat);
    }
}
Решение проблемы - прервать цикличный вызов, убрав из метода поле. @ToString.Exclude - Исключить поле в методе toString @EqualsAndHashCode.Exclude - Исключить поле в методе equals и hashCode

@Value
@With
@Builder
public class Cat {
    String name;
    int age;
    @ToString.Exclude
    @EqualsAndHashCode.Exclude
    Person person;
}
Еще пара полезных аннотаций @Slf4j - добавляет в класс логгер log @SneakyThrows - делает проверяемые исключения непроверяемыми

@Slf4j
public class Main {

    @SneakyThrows
    public static void main(String[] args) {
        log.info("start");
        Files.readAllBytes(Paths.get(""));
    }
}
Аннотации по отдельности Если по каким-либо причинам вам нужны только определенные методы

@NoArgsConstructor //добавляет конструктор без аргументов
@AllArgsConstructor //добавляет конструктор со всеми параметрами
@RequiredArgsConstructor //добавляет конструктор для final полей
@Getter //добавляет геттеры для всех параметров класса
@Setter //добавляет сеттеры для всех параметров класса
@EqualsAndHashCode //добавляет реализации методов equals и hashCode
@ToString //добавляет реализацию метода toString
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) //делает все поля private и final
Библиотека Lombok - 2<h2>Заключение</h2>Это только основные аннотации lombok, но они чаще всего используются и дают максимальный эффект. Слишком сильно увлекаться генерацией кода тоже не стоит. <h2>Ссылки</h2>
Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #3162843 Уровень 18
2 апреля 2023
Что значит @Slf4j - добавляет в класс логгер log,может кто-нибудь подробнее рассказать об этом
Artur Уровень 23
16 февраля 2022
Забыли про @Accessors(chain = true) - позволяет сеттерам возвращать объект и выстраивать его в цепочку для присвоения значений, как делает это Builder.
Vladimir Komarov Уровень 41
4 июня 2020
Убираем геттеры-сеттеры, но добавляем кучку анонотаций и необходимость поддержки всего этого. Так себе инфраструктурная затея.