Перейти к содержимому

Lombok java что это

  • автор:

Lombok — Java: Классы

В Java разработчики часто сталкиваются с необходимостью написания повторяющегося шаблонного кода. К таким элементам относятся конструкторы, геттеры и сеттеры. Это может приводить к значительному увеличению объема кода, особенно в больших проектах.

Рассмотрим класс Post . Он содержит пять полей, включающих стандартные конструкторы и методы доступа. Это типичный пример шаблонного кода, который встречается во многих классах.

import java.time.LocalDate; public class Post  private Long id; private Long authorId; private String slug; private String name; private String body; private LocalDate createdAt; // Конструктор по умолчанию public Post()  > // Конструктор со всеми полями public Post(Long id, Long authorId, String slug, String name, String body, LocalDate createdAt)  this.id = id; this.authorId = authorId; this.slug = slug; this.name = name; this.body = body; this.createdAt = createdAt; > public Long getId()  return id; > public void setId(Long id)  this.id = id; > public Long getAuthorId()  return authorId; > public void setAuthorId(Long authorId)  this.authorId = authorId; > public String getSlug()  return slug; > public void setSlug(String slug)  this.slug = slug; > public String getName()  return name; > public void setName(String name)  this.name = name; > public String getBody()  return body; > public void setBody(String body)  this.body = body; > public LocalDate getCreatedAt()  return createdAt; > public void setCreatedAt(LocalDate createdAt)  this.createdAt = createdAt; > > 

Мы еще не написали ничего полезного, но класс уже занимает больше 70 строк. А что будет когда у нас будет 20 полей или 30? Для прикладного кода это вполне нормально. При этом самих классов сотни и тысячи. Некоторых разработчиков такая ситуация устраивает, так как редактор сам генерирует весь нужный код, но некоторые все равно хотели бы избавиться от шаблонного кода и даже не генерировать его.

Решение с Lombok

Сама Java не позволяет так сделать, но позволяет Lombok . Lombok – это библиотека, которая позволяет убрать шаблонный код при создании классов. Возьмем класс из примера выше и перепишем его с использованием Lombok. Вот что у нас получится.

import java.time.LocalDate; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Post  private Long id; private Long authorId; private String slug; private String name; private String body; private LocalDate createdAt; > 

Размер класса сократился до примерно 10 строк, хотя то что мы получили – это всего лишь визуальное сокращение кода. Во время исполнения этот код будет заменен на обычный класс Java со всеми нужными методами.

Самое необычное в коде выше это блок кода над классом:

import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @NoArgsConstructor @AllArgsConstructor 

То, что мы здесь видим, называется аннотациями. Аннотации в Java это тоже код. Аннотации бывают у классов, методов и даже параметров методов. Они начинаются с символа @ за которым идет имя аннотации. Аннотации могут сопровождаться параметрами в стиле, похожем на вызов функций.

@Annotation(key=value) // определение какого-нибудь класса 

То что мы увидели выше, называется аннотациями класса. Встречаются и другие аннотации, привязанные к свойствам, методам и даже параметрам методов. Со временем мы разберемся со всеми видами и будем их активно использовать в своем коде не только в связке с Lombok.

Сами по себе аннотации на код никак не влияют. Аннотации лишь добавляют информацию к классу, которую затем может прочитать и использовать другой код. В нашем случае это будет делать плагин Lombok для Gradle, который подключается к проекту таким образом:

plugins  id("io.freefair.lombok") version "8.4" > 

Lombok встраивается в процесс компиляции, во время которой он «наполняет» классы необходимыми методами. Из-за этого, помимо gradle-плагина, для поддержки Lombok понадобится добавить плагин в используемый редактор. Подробнее установка Lombok описана на официальном сайте .

За что отвечает каждая аннотация выше?

  • @Getter : Генерирует стандартные геттеры для всех полей класса.
  • @Setter : Генерирует стандартные сеттеры для всех полей класса.
  • @NoArgsConstructor : Генерирует пустой конструктор. Используется только тогда, когда определен хотя бы один не пустой конструктор.
  • @AllArgsConstructor : Генерирует конструктор со всеми полями. Поля в конструкторе перечислены в том же порядке, в котором они определены в классе.

@ToString

@toString еще одна полезная аннотация, которая генерирует метод toString() добавляя в него все не статические поля класса.

import lombok.ToString; @ToString // Остальные аннотации public class User  private String name; private int age; private String email; > 

Использование и вывод:

var user = new User("John Doe", 30, "john.doe@example.com"); System.out.println(user); // => User(name=John Doe, age=30, email=john.doe@example.com) 

@EqualsAndHashCode

Аннотация @EqualsAndHashCode генерирует методы equals() и hashCode() соответственно. По умолчанию, в эти методы включаются все не статические поля класса. Пример с пользователем.

import lombok.EqualsAndHashCode; @EqualsAndHashCode // Остальные аннотации public class Person  private String name; private int age; private String email; > 
var person1 = new Person("John Doe", 30, "john.doe@example.com"); var person2 = new Person("John Doe", 30, "john.doe@example.com"); System.out.println(person1.equals(person2)); // true System.out.println(person1.hashCode()); // hashCode of person1 System.out.println(person2.hashCode()); // hashCode of person2 (идентичен с person1) 

Если поведение необходимо изменить, то @EqualsAndHashCode позволяет это сделать описав те поля, которые нужно явно включить или исключить. Предположим что мы хотим сравнивать пользователей только на основе email, тогда код примет следующий вид:

@EqualsAndHashCode(onlyExplicitlyIncluded = true) public class Person  private String name; private int age; @EqualsAndHashCode.Include 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Библиотека Lombok

Java-университет

Библиотека Lombok - 1

Библиотека Lombok сокращает количество написанного кода, улучшая читаемость. Пример использования. Обычный класс 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 @Data public class Person

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

 @Value public class Cat

С неизменяемыми классами хорошо сочетаются аннотации @With и @Builder .

 @With @Builder @Value public class Cat

Если мы хотим у неизменяемого объекта поменять поле, то нам нужно сделать клон этого объекта с одним измененным параметром. @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

Еще пара полезных аннотаций @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: хорошее и плохое применение

Lombok — по-настоящему хороший инструмент, который помогает писать меньше кода и больше сосредотачиваться на реальной работе. Суть в том, как вы используете Lombok в проекте: есть как хорошие, так и плохие способы использования.

Что такое Lombock

Lombok — это библиотека Java, которая сокращает объем стандартного кода в классах. Вы добавляете аннотации, и Lombok генерирует код во время компиляции. Например, если аннотировать класс с помощью @Getter , то Lombok сгенерирует методы-геттеры для всех переменных в классе.

Как работает Lombock

Начнем с того, как происходит процесс компиляции. В нем есть три основных этапа:

  • разбор и ввод;
  • обработка аннотаций;
  • анализ и генерация.

На этапе разбора и ввода исходные файлы считываются в синтаксическое дерево (AST), и каждое дерево передается на ввод. Все обработчики аннотаций вызываются на этапе обработки аннотаций. Если обработчики аннотаций генерируют новые исходные файлы или файлы классов, процесс компиляции переходит к первым шагам и все запускается заново. Так повторяется до тех пор, пока не появятся новые исходные файлы или файлы классов, созданные обработчиками аннотаций. AST преобразуется в файл класса на этапе анализа и генерации.

Вся магия Lombock происходит на этапе обработки аннотаций. Задача процессора аннотаций заключается в создании новых исходных файлов или классов, но вместо этого Lombock изменяет существующие. Нигде в спецификации компилятора Java не утверждается, могут или не могут обработчики аннотаций изменять существующий исходный файл. Lombock использует эту лазейку в своих интересах. Мы можем изменить класс, который будет сгенерирован из исходного кода, изменив AST. Вот как работает Lombock.

Преимущества Lombock

Lombock упрощает написание кода, позволяя сосредоточиться только на том, что нужно реализовать, а именно — переводе бизнес-требований в код. Написание геттеров, сеттеров, конструкторов, методов equals или реализация шаблона конструктора — это не то, на что мы должны тратить время.

Lombock позаботится об этом, просто нужно добавить подходящую аннотацию, и он сгенерирует код. Например, если нужно создать геттеры и сеттеры, достаточно аннотировать класс с помощью @Getter и @Setter .

Если у вас сложный объект со многими атрибутами, вы можете аннотировать класс с помощью @Builder , и Lombok реализует шаблон builder для этого класса.

Вот скомпилированный код вышеупомянутого класса:

Есть также множество дополнительных аннотаций, которыми можно воспользоваться в проектах, чтобы писать меньше кода, например @Cleanup , @AllArgsConstructor , @Data и @Value . Меньше кода означает меньше поводов к беспокойству. Однако Lombock добавляет код в проект во время компиляции — и иногда его оказывается больше, чем если бы вы писали самостоятельно.

Плохое применение Lombock

Иногда разработчики забывают, что Lombok генерирует код, потому что его не видно в исходном коде.

Прежде чем что-либо реализовать, многие добавляют аннотации Lombock в классы. Например, аннотируют классы DTO, используя аннотацию @Data для создания геттеров и сеттеров. Но они забывают (или не знают), что Lombock генерирует дополнительные методы, такие как equals , hashCode , toString и canEqual . Иногда они просто не нужны, а в репозитории не должно быть ничего, что мы не используем.

У любого кода должна быть причина для существования, а если ее нет, его необходимо удалить. Ответственность за применение правильных аннотаций Lombock лежит на разработчиках. Наиболее очевидный способ исправить это — добавить аннотации @Getter и @Setter вместо аннотации @Data .

Некоторые разработчики пользуются Lombock, чтобы скрывать нарушения Sonar, а не исправлять их (намеренно или непреднамеренно). Возьмите в качестве примера приведенный ниже код:

У этого конструктора — девять параметров, и это нарушение Sonar.

Класс может делать слишком много. Это должно быть исправлено путем внесения необходимых изменений в код. Разработчики берут @Requiredargsconstructor для создания конструктора с требуемыми параметрами. Но когда они добавляют эту аннотацию, нарушение Sonar не подсвечивается.

Так не стоит справлять нарушение.

Кроме того, лучше не использовать какую-либо аннотацию Lombock, если она изменяет код. Если вы берете @Data , @Getter , @Setter или @AllArgsConstructor , то добавляете новый код в существующий без изменения написанного. Но если взять аннотацию @Utilityclass , она изменит код. К примеру, вот утилитный класс ниже:

Аннотация @Utilityclass преобразует существующий класс в утилитный, делая его окончательным и создавая приватный конструктор по умолчанию. Она также изменяет существующий метод и переменные, делая их статическими. Если вы проверите вышеуказанный класс, то не обнаружите никаких проблем. Нарушений Sonar также нет. Но при проверке скомпилированного кода вы увидите реальные проблемы:

Переменная value является общедоступной статической конечной переменной, поэтому она должна соответствовать соглашению об именовании констант. Но когда мы проверяем исходный код, то видим, что это переменная экземпляра. Даже IDE не смогла идентифицировать ее как константу. Можно утверждать, что если знать, как работает аннотация @Utilityclass , то понятно: переменная value — константа. Такого рода модификации плохо влияют на читаемость. В первую очередь код должен быть удобочитаемым для человека. И на человеческий взгляд, это переменная экземпляра.

Еще одно, что стоит иметь в виду, — Lombock использует лазейку в спецификации компилятора Java. Если Java исправит это, мы, возможно, не сможем дальше пользоваться Lombock.

Заключение

Lombock — хороший и полезный инструмент. Но стоит использовать его разумно. Если не знать этого, то реальные преимущества Lombock останутся для нас недоступны.

  • Java-Lombok: нужны ли геттеры и сеттеры?
  • String, StringBuilder и StringBuffer: понимаете ли вы разницу?
  • Основы многопоточности

Безопасно ли использование Project Lombok?

Java — это мощный язык программирования, который используется во многих видах разработки. Однако, как и все языки, он имеет свои недостатки, и одним из них является необходимость писать многословный код для создания простых объектов, таких как геттеры и сеттеры. Рассмотрим простой пример — у вас есть класс с пятью полями. Для каждого поля вам придется написать геттер и сеттер, что приведет к десяти дополнительным методам.

Проект Lombok предлагает решение для этой проблемы. Это библиотека, которая автоматически генерирует код для геттеров, сеттеров и других общих элементов с помощью аннотаций. Например, вместо того чтобы писать десять методов для нашего примера выше, вы можете просто добавить аннотацию @Data к вашему классу, и Lombok сгенерирует все необходимые методы за вас.

Однако возникает вопрос: безопасно ли использовать Lombok в ваших проектах?

Как и все инструменты, Lombok имеет свои плюсы и минусы. С одной стороны, он может значительно упростить ваш код и сделать его более читаемым. Это может быть особенно полезно в больших проектах, где многословный код может быстро стать проблемой.

С другой стороны, Lombok это не стандартная библиотека и ее использование может привести к проблемам совместимости и понимания кода другими разработчиками.

Например, некоторые разработчики могут не быть знакомы с Lombok и не понимать, что делают аннотации. Это может создать препятствия для сотрудничества и обмена кодом.

Кроме того, поскольку Lombok не является стандартной библиотекой, существует риск, что она может стать несовместимой с новыми версиями Java или другими библиотеками.

В целом, безопасно ли использование Lombok, в значительной степени зависит от контекста. Если вы работаете над небольшим проектом или экспериментируете, Lombok может быть полезным инструментом для упрощения вашего кода. Если же вы работаете над большим проектом с большим количеством разработчиков, которые могут не быть знакомы с Lombok, то может быть целесообразно избегать его использования.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *