JavaRush/Java блог/Random/Аннотации. Часть вторая. Lombok

Аннотации. Часть вторая. 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 Java Developer в BIFIT Expert
11 марта 2022, 15:26
В новой джаве наряду с классами появился тип данных - record. По сути - то же, что и класс с ломбоковской @Data. Просто прописываем поля в аргументах типа и вуаля. Можно пользоваться, и никакие конструкторы не нужны. Из минусов - публичный доступ к полям. Может, как-то можно настроить глубже, я не проверял пока.
Kurama
Уровень 50
12 апреля 2023, 20:08
А в чем проблема? Твои геттеры же публичные
LuneFox Java Developer в BIFIT Expert
13 апреля 2023, 11:02
Проблема не в геттерах, а в сеттерах.
Сергеев Виктор
Уровень 40
Master
13 апреля 2023, 18:23
Не пользовался самим record классами, но он разве не immutable? https://openjdk.org/jeps/395 "A record class is implicitly final, and cannot be abstract. These restrictions emphasize that the API of a record class is defined solely by its state description, and cannot be enhanced later by another class."
Kurama
Уровень 50
14 апреля 2023, 20:54
Вроде бы record эквивалентен классу с приватными полями, которые инициализируются через конструктор, сеттеров к которым нет. С переопределенными хэшкодом и иквэлсом
Сергей Java Developer в Адвантум
1 сентября 2021, 14:44
А где следующая статья? Автор, очень интересно пишешь. Спасибо!
Mikhail
Уровень 40
14 апреля 2021, 09:40
Аннотации работают через рефлексию, что в свою очередь может сказаться на производительность. Похоже на то что не стоит использовать их без особой необходимости, например в угоду тому что "вам сложно видеть много геттеров и сеттеров".
Сергеев Виктор
Уровень 40
Master
14 апреля 2021, 11:15
ломбок аннотации отрабатывают на этапе компиляции, переписывая байт код. В первой часты как раз был разбот типов аннотаций и когда они используются компилятором или jvm Например у @Data (https://projectlombok.org/api/lombok/Data.html) Retention указан как SOURCE
Mikhail
Уровень 40
14 апреля 2021, 11:46
В таком случае удобная штука, спасибо за инфу.
Valua Sinicyn
Уровень 41
1 марта 2021, 17:07
Бородатые деды не рекомендуют использовать эту хрень.
Нейросеть
Уровень 41
10 сентября 2023, 15:20
А в блокноте код писать не рекомендуют?)
Lizaveta:)
Уровень 16
13 октября 2020, 06:34
Классно получилось, спасибо за статью! Есть ли еще что-то подобное об аннотациях @Variable и @Builder ?
Владислав Backend Developer
21 июля 2020, 07:41
А где следующая часть? Про runtime?
Джамал
Уровень 20
31 июля 2019, 11:52
а как с помощью аннотации установить ограничения для сеттера переменной age, то что он не может быть отрицательным?
Сергеев Виктор
Уровень 40
Master
31 июля 2019, 17:14
Для сеттера никак, сеттер будет сгенерирован при сборке проекта. Ограничение можно установить используя javax.validation Например @Min(0) укажет, что минимальное значение атрибута должно быть 0
Anonymous #2491313 Java Developer в Росатом
28 апреля 2021, 07:21
Для тех, у кого лапки, пойдёт ).
dimskiy Android Developer в Revolut
14 мая 2018, 06:16
... или просто переходите на Kotlin, если есть такая возможность :)
Сергеев Виктор
Уровень 40
Master
28 мая 2018, 17:32
А чем котлин принципиально лучше ломбока? Вы уже второй с таким советом, но если мне нужны только фичи ломбока, зачем мне добавлять другой язык? Тем более это потом будут читать другие и возможно у них не будет времени разбираться с ненужным им языком ))
dimskiy Android Developer в Revolut
22 декабря 2018, 22:17
Запоздало, но отвечу. Ломбок - костыли для Джава, чтобы быть хотя бы немного удобнее. В котлине гибкая работа с сеттерами-геттерами (как и дохренилион всего другого) уже встроено by design. Если хотите, это боллее современный и быстрый язык разработки, который для знающего Джаву изучается довольно быстро. А если мы говорим про Андроид-разработку, то переход на котлин носит прямо-таки массовый характер и противится ему как-то странно.
Сергеев Виктор
Уровень 40
Master
23 декабря 2018, 11:51
Если так подумать то котлин тоже костыли для джавы =) Ломбок не панацея, есть много других интересных способов получить дтошки. В последнем проекте мы генерили их из схем, геттеры и сеттеры там идут автоматом. А вообще каждый язык под свое заточен. Я плохо представляю как вы будете внедрять новый язык в старый проект под предлогом "там геттеры и сеттеры писать не надо". Причем что это может послечь за собой огромные финансовые затраты, при этом нулевой профит ) Так что давайте каждый останется при своем мнении, java тем и хороша, что есть много удобных инструментов как ломбок и котлин, чтобы каждый мог выбрать удобное для себя )
dimskiy Android Developer в Revolut
22 января 2019, 22:05
Котлин отлично внедряется в старые проекты, особенно если делать это по частям при допиле нового функционала. Разумеется, давайте останемся при своих мнениях, однако проблем как вы описываете просто нет. Котлин настолько прозрачно интегрируется в проект, что не требует ни огромных затрат на переписывание всего заново, ни сложной интеграции с имеющимся кодом на Джаве. Это просто надо посмотреть своими глазами, чтобы перестать "плохо представлять".
Сергеев Виктор
Уровень 40
Master
23 января 2019, 22:12
"Котлин отлично внедряется в старые проекты, особенно если делать это по частям при допиле нового функционала." - т.е. выделить время, убедить бизнес, что это нужно и на это стоит тратить деньги. При этом снизить количество людей способных поддерживать проект... "Это просто надо посмотреть своими глазами, чтобы перестать "плохо представлять"." Представим проект, которому уже 15 лет. В нем есть весь зоопарк java, там есть ещё груви в скриптах, куча xml и прочие ужасы. Вы предлагаете в такой проект добавить другой язык? И все ради того, чтобы в некоторой части дто не генерить гет/сет? Не кажется ли вам, что это пушкой по воробьям? Я не спорю, котлин может быть хорошо и у него есть свои фишки, но он не панацея, это такой же костыль как и ломбок в части геттеров и сеттеров.
vinsler
Уровень 35
Expert
5 марта 2018, 18:50
народ ругал ломбок, мол там непонятно что внутри, что нет тестов на библиотеку, что потом могут вылезти какие-то ошибки, и что их хрен найдешь, я не тестил, поэтому только со слов.
Сергеев Виктор
Уровень 40
Master
8 марта 2018, 13:09
киньте ссылочку на обсуждение, сам почитаю, а то пользуюсь и похоже что-то не знаю
vinsler
Уровень 35
Expert
9 марта 2018, 19:47
Вик это в телеге чат java, конкретных людей не помню, уже оттуда ушел, т.к. на любой вопрос могу найти ответ пока что сам. Постоянные срачи на фоне ломбока там однозначно были, не вникал в кишки, пока что не юзаю потому что.
Сергеев Виктор
Уровень 40
Master
9 марта 2018, 20:59
не знаю, в нашем чате он зашел на ура =) В защите ломбока скажу про спринг, в инициализаторе boot от точно есть, вроде даже в сорсах спринга его видел (классы не вспомню, поэтому не считается)
Юрій Якимчук
Уровень 33
3 марта 2018, 13:51
А они уже допилили его хотя б до 9й джавы? :)
Сергеев Виктор
Уровень 40
Master
3 марта 2018, 20:26
а че там в 9 сильно изменилось в плане геттеров, сеттеров и прочего? Это всегда пишет создатель класса.
Аслан Backend Developer в Mail.ru Group Expert
23 марта 2018, 23:51
Идея добавить val, var в Java не нова, и Тагир по этому поводу негодует.
Сергеев Виктор
Уровень 40
Master
24 марта 2018, 00:41
в данном случае это не идея, а вполне готовый проект, который уже используется на практике =)