JavaRush /Java блог /Random /Аннотации. Часть вторая. Lombok
Сергеев Виктор
40 уровень

Аннотации. Часть вторая. Lombok

Статья из группы Random
Аннотации. Часть первая, немного скучная В этой части я решил затронуть библиотеку Lombok как известного представителя Source аннотаций. С Runtime аннотациями в следующей статье. Жил был java программист, каждый день он писал обычный код, например такой:

package lombok;

public class Chelovek {
    private String name;
    private int age;

    public Chelovek(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Chelovek() {
    }

    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;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Chelovek chelovek = (Chelovek) o;

        if (age != chelovek.age) return false;
        return name != null ? name.equals(chelovek.name) : chelovek.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Chelovek{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
Обычный такой класс, всего 2 поля (а ведь бывает и больше 10-15 полей). Да конечно это все можно генерировать в IDE, но блин, оно место занимает. Если полей 15-20, ко всем нужны геттеры, сеттеры, конструкторы… Среди всего этого легко может потеряться пара другая методов, незаметных глазу. Как помочь такому программисту, чтобы писал быстрее и меньше? Lombok. Сразу в пекло, тот же класс но с использование ломбока:

package lombok;

@Data
public class Chelovek {
    private String name;
    private int age;
}

Да это все. Прикольно? Что сделает аннотация @Data? Она на этапе компиляции сгенерирует геттеры\сеттеры для всех полей, toString и переопределит equals и hashCode по стандартам. В IDE можно установить плагин и он будет видеть все ещё не созданные методы.
Аннотации. Часть вторая. Lombok - 1
Надеюсь тут тебе, читатель, стало интересно, потому что дальше будет коротка вводная и ссылки на подробности. Ломбок так же предоставляет возможность кастомизировать генерацию, не всегда же нужны все геттеры, сеттеры или хешкод надо генерировать по-другому. Поэтому есть отдельные аннотации (думаю, многие из них в описании не нуждаются) @Getter/@Setter @ToString @EqualsAndHashCode @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor @Log Это самые типичные, весь набор можно посмотреть тут Особого внимания достойный var и val. Это возможность писать так:

package lombok;

import lombok.experimental.var;

@Data
public class Chelovek {
    private String name;
    private int age;

    public static void main(String[] args) {
        var chelovek = new Chelovek();
        chelovek.setAge(22);
        System.out.println(chelovek);
    }
}

Зачем это нужно? Например у нас есть класс RandomAccessFileChannel Ну, зачем нам писать так:

RandomAccessFileChannel channel = new RandomAccessFileChannel();
Если можно так:

var channel2 = new RandomAccessFileChannel();
На мой взгляд, это не всегда приемлемо. Например, у нас есть злой метод, возвращающий злую мапу:

public static Map<List<Set<Integer>>, Set<List<String>>> evilMap(){
    return new HashMap<>();
}

если вызывать его так:

Map<List<Set<Integer>>, Set<List<String>>> listSetMap = evilMap();
То более менее понятно с чем мы работаем. Если же вызов такой:

var listSetMap = evilMap();
то хрен знает, что там возвращает evilMap(), и пока не посмотришь в сам метод, не узнаешь. А зачем бегать по исходникам? В общем, с этим надо быть аккуратнее. Экспериментальная ветка: Тут хочу отметить аннотации: @UtilityClass Она создает приватный конструктор и там бросает exception (чтоб ручки грязные от рефлексии не лезли сюда). И очень красиво в начале класса сообщает нам, что тут утилитные методы. @Delegate Реализует шаблон делегирования. Если у тебя есть класс, который что-то делегирует другому классу, при этом вносит изменения только в некоторые методы, эта аннотация избавит тебя от дублирования методов + будет следить за ними. Если метод удалили или добавили, она это заметит. Ветка экспериментальных аннотаций GITHUB Официальный сайт Для того, чтобы IDE нормально работала с lombok, и не подчеркивала методы как несуществующие, надо установить плагин. На официальном сайте, есть раздел setup в котором можно посмотреть как подключить плагин для каждой IDE Как можно заметить ломбок популярен. >5000 звезд и >1000 форков. Спринг в своих классах использует ломбок. Если у тебя в проекте есть спринг, поищи, возможно, он подтянул ломбок, просто ты не в курсе.
Комментарии (34)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
LuneFox Уровень 41 Expert
11 марта 2022
В новой джаве наряду с классами появился тип данных - record. По сути - то же, что и класс с ломбоковской @Data. Просто прописываем поля в аргументах типа и вуаля. Можно пользоваться, и никакие конструкторы не нужны. Из минусов - публичный доступ к полям. Может, как-то можно настроить глубже, я не проверял пока.
Сергей Уровень 32
1 сентября 2021
А где следующая статья? Автор, очень интересно пишешь. Спасибо!
Mikhail Уровень 40
14 апреля 2021
Аннотации работают через рефлексию, что в свою очередь может сказаться на производительность. Похоже на то что не стоит использовать их без особой необходимости, например в угоду тому что "вам сложно видеть много геттеров и сеттеров".
Valua Sinicyn Уровень 41
1 марта 2021
Бородатые деды не рекомендуют использовать эту хрень.
Lizaveta:) Уровень 16
13 октября 2020
Классно получилось, спасибо за статью! Есть ли еще что-то подобное об аннотациях @Variable и @Builder ?
Владислав Уровень 41
21 июля 2020
А где следующая часть? Про runtime?
Джамал Уровень 20
31 июля 2019
а как с помощью аннотации установить ограничения для сеттера переменной age, то что он не может быть отрицательным?
dimskiy Уровень 28
14 мая 2018
... или просто переходите на Kotlin, если есть такая возможность :)
vinsler Уровень 35 Expert
5 марта 2018
народ ругал ломбок, мол там непонятно что внутри, что нет тестов на библиотеку, что потом могут вылезти какие-то ошибки, и что их хрен найдешь, я не тестил, поэтому только со слов.
Юрій Якимчук Уровень 33
3 марта 2018
А они уже допилили его хотя б до 9й джавы? :)