Цикл статей «Project Lombok».
Следующая статья — «Lombok @Value — лёгкое создание неизменяемых классов».
Предыдущая статья — «Lombok @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor».
@Data — это удобная сокращённая аннотация, которая содержит в себе возможности из @ToString, @EqualsAndHashCode, @Getter / @Setter и @RequiredArgsConstructor. Другими словами, @Data генерирует весь бойлерплейт код, который обычно связан с обычными POJO (Plain Old Java Objects) и бинами: методы получения значений для всех полей, методы установки значений для не final полей, подходящий toString, equals и hashCode для этих полей, конструктор, инициализирующий все final поля и все не final поля, у которых нет выражения инициализации, и которые помечены @NonNull, для того чтобы гарантировать, что поле никогда не будет null.
@Data — это всё равно, что иметь неявные @Getter, @Setter, @ToString, @EqualsAndHashCode и @RequiredArgsConstructor для класса (с исключением что никаких конструкторов не генерируется, если уже есть явно написанный конструктор). Однако параметры этих аннотаций (callSuper, includeFieldNames и exclude) не могут быть установлены с @Data. Если вам нужно установить значение этих параметров отличное от значения по умолчанию, то просто явно добавьте эти аннотации. @Data достаточно умён, чтобы учитывать их.
Все сгенерированные методы получения значений и установки значений будут с модификатором доступа public. Чтобы переопределить уровень доступа, добавьте @Getter, @Setter к полю или классу. Вы можете также использовать эти аннотации (комбинируя их с AccessLevel.NONE), чтобы подавить генерацию методов установки значений и/или методов получения значений.
Все поля помеченные как transient не будут рассматриваться в hashCode и equals. Все статические поля будут пропускаться полностью (не рассматриваются любыми сгенерированными методами, и для них не будет сгенерировано методов получения/установки значений).
Если класс уже содержит метод с таким же именем и количеством параметров, как метод, который должен быть сгенерирован, то метод не генерируется, и ошибок и предупреждений не возникает. Например, если уже есть метод с сигнатурой equals(AnyType param), то метод equals не будет сгенерирован, несмотря на то что технически это может быть совершенно другой метод, так как у него другой тип параметра. То же правило применяется для конструктора (при наличии явного конструктора @Data не генерирует конструкторов), так же как и для toString, equals, методов получения значений, методов установки значений. Вы можете пометить любой конструктор или метод @lombok.experimental.Tolerate, чтобы скрыть его от Lombok.
@Data может обрабатывать шаблонные параметры для полей. Для того чтобы уменьшить бойлерплейт-код при создании объектов для классов с шаблонами, вы можете использовать параметр staticConstructor, чтобы сгенерировать приватный конструктор, а также статический метод, возвращающий новый экземпляр. В этом случае javac будет выводить тип переменной. Таким образом, с объявлением класса @Data(staticConstructor="of") class Foo { private T x;}, вы можете создавать экземпляры класса Foo так: Foo.of(5);, вместо new Foo(5);.
С помощью Lombok
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import lombok.AccessLevel; import lombok.Setter; import lombok.Data; import lombok.ToString; @Data public class DataExample { private final String name; @Setter(AccessLevel.PACKAGE) private int age; private double score; private String[] tags; @ToString(includeFieldNames = true) @Data(staticConstructor = "of") public static class Exercise<T> { private final String name; private final T value; } } |
Чистая Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
import java.util.Arrays; public class DataExample { private final String name; private int age; private double score; private String[] tags; public DataExample(String name) { this.name = name; } public String getName() { return this.name; } void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void setScore(double score) { this.score = score; } public double getScore() { return this.score; } public String[] getTags() { return this.tags; } public void setTags(String[] tags) { this.tags = tags; } @Override public String toString() { return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")"; } protected boolean canEqual(Object other) { return other instanceof DataExample; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof DataExample)) return false; DataExample other = (DataExample) o; if (!other.canEqual((Object) this)) return false; if (this.getName() == null ? other.getName() != null : !this.getName() .equals(other.getName())) return false; if (this.getAge() != other.getAge()) return false; if (Double.compare(this.getScore(), other.getScore()) != 0) return false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long temp1 = Double.doubleToLongBits(this.getScore()); result = (result * PRIME) + (this.getName() == null ? 43 : this.getName().hashCode()); result = (result * PRIME) + this.getAge(); result = (result * PRIME) + (int) (temp1 ^ (temp1 >>> 32)); result = (result * PRIME) + Arrays.deepHashCode(this.getTags()); return result; } public static class Exercise<T> { private final String name; private final T value; private Exercise(String name, T value) { this.name = name; this.value = value; } public static <T> Exercise<T> of(String name, T value) { return new Exercise<T>(name, value); } public String getName() { return this.name; } public T getValue() { return this.value; } @Override public String toString() { return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")"; } protected boolean canEqual(Object other) { return other instanceof Exercise; } @Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Exercise)) return false; Exercise<?> other = (Exercise<?>) o; if (!other.canEqual((Object) this)) return false; if (this.getName() == null ? other.getValue() != null : !this .getName().equals(other.getName())) return false; if (this.getValue() == null ? other.getValue() != null : !this .getValue().equals(other.getValue())) return false; return true; } @Override public int hashCode() { final int PRIME = 59; int result = 1; result = (result * PRIME) + (this.getName() == null ? 43 : this.getName().hashCode()); result = (result * PRIME) + (this.getValue() == null ? 43 : this.getValue() .hashCode()); return result; } } } |
Поддерживаемые ключи конфигурации
1 |
lombok.data.flagUsage = [warning | error] (default: not set) |
Lombok будет помечать любое использование @Data предупреждением или ошибкой, если настроено.
Примечание
Смотрите примечания к @ToString, @EqualsAndHashCode, @Getter / @Setter и @RequiredArgsConstructor.
Любые аннотации с именем @NonNull (нечувствительно к регистру) для поля расцениваются как то, что это поле никогда не должно содержать null. Поэтому эти аннотации приведут к проверке на null в сгенерированном конструкторе для этих полей. Также эти аннотации (как и все аннотации с именем @Nullable) копируются к параметру конструктора, настоящему или статическому. Те же принципы применяются к сгенерированным методам получения значений и установки значений (смотрите статьи про @Getter / @Setter)
По умолчанию любые переменные, начинающиеся с символа «$», исключаются автоматически. Вы можете включить их с помощью явных аннотаций (@Getter или @ToString, например) или с помощью параметра of.
Цикл статей «Project Lombok».
Следующая статья — «Lombok @Value — лёгкое создание неизменяемых классов».
Предыдущая статья — «Lombok @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor».
«Lombok будет помечать любое использование @Data предупреждением или ошибкой, если настроено.» — если настроено что? …………..