Lombok конструктор с несколькими параметрами

Обновлено: 19.04.2024

If I add annotation @AllArgsConstructor than I can't see default constructor.

Is it possible to have both constructor in Lombok ?

4 Answers 4

Your class is equivalent to:

Although strictly speaking this adds toString , equals and hashCode methods on all variables. This can (and often does) cause infinite loops. Be very wary of @Data .

@Accessors(chain = true) makes the setter implementations return this , more info here.

You can add multiple constructor annotations:

Unlike most other lombok annotations, the existence of an explicit constructor does not stop these annotations from generating their own constructor.

Note that @Accessors is experimental so may be changed/renamed at some future point.

I prefer @Builder to @AllArgsConstructor as it allows only required parameters to be set, whereas a all arguments constructor is all or nothing. It also generates much more readable code, consider

I'd semi-deprecate @Accessors in favor of configuration. Concerning constructors, I rather use exclusively @RequiredArgsConstructor . Combined with Guice, it means, I just declare a field and can use it (no constructor calls in code).

Have you tried this?

for some reason in my case this creates only the first constructor (no args), and ignores the second one. If I flip the order, the issue is flipped as well.

Yes, you can use both constructor in Lombok.

@AllArgsConstructor generates a constructor requiring an argument for every field in the annotated class.

So we have the Employee class with two fields:

When we de-lombok the class, it becomes:

@NoArgsConstructor generates a default constructor with no parameters.

We have the following Employee class:

When we look at the generated code, we see that Lombok adds a no-args constructor:

Try this. This should work. Add this annotation as well.

@NoArgsConstructor will generate a constructor with no parameters. If this is not possible (because of final fields), a compiler error will result instead, unless @NoArgsConstructor(force = true) is used, then all final fields are initialized with 0 / false / null. For fields with constraints, such as @NonNull fields, no check is generated,so be aware that these constraints will generally not be fulfilled until those fields are properly initialized later. Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor. This annotation is useful primarily in combination with either @Data or one of the other constructor generating annotations.

Аннотация @Builder была представлена как новая возможность в Lombok v0.12.0.

Аннотация @Builder получила поддержку @Singular и была переведена в основной пакет Lombok в Lombok v1.16.0.

Аннотация @Builder создаёт составной builder API для ваших классов.

@Builder даёт вам возможность автоматически генерировать код, необходимый для создания экземпляров ваших классов кодом вида:

Person . builder ( ) . name ( "Adam Savage" ) . city ( "San Francisco" ) . job ( "Mythbusters" ) . job ( "Unchained Reaction" ) . build ( ) ;

@Builder может быть указан для класса или конструктора или статического метода. Чаще всего он указывается для класса или для конструктора, но легче его объяснить на примере статического метода.

Статический метод с аннотацией @Builder (дальше я буду называть его целью) приводит к генерации семи вещей:

  • Статический вложенный класс с именем FooBuilder и с теми же аргументами, что и статический метод (называемый builder).
  • В builder: Одно приватное нестатическое поле для каждого параметра в цели.
  • В builder: Пустой конструктор без аргументов с модификатором доступа package private.
  • В builder: Метод для установки значения для каждого параметра. Он имеет тот же тип аргумента, что и параметр и то же имя. Он возвращает builder, так что методы установки значения могут быть выстроены в цепочку, как в примере выше.
  • В builder: Метод build(), вызывающий статический метод, передающий туда все поля. Он возвращает тот же тип, что и цель.
  • В builder: Подходящая реализация toString().
  • В классе, содержащем цель: Статический метод builder(), который создаёт экземпляр builder-а.

Любой из перечисленных элементов для генерации просто пропускается, если элемент уже существует (не зависимо от количество параметров, смотрится только имя). Это касается и самого builder — если класс уже существует, то Lombok просто вставляет поля и методы в уже существующий класс, если этих полей/методов ещё нет, конечно. Поэтому вы не можете добавлять любую другую аннотацию Lombok, генерирующую метод или конструктор к builder-у. Например, вы не можете добавить @EqualsAndHashCode к классу builder-а.

@Builder может генерировать так называемые singular-методы. Они берут один параметр вместо целого списка и добавляют элемент к списку. Например: Person . builder ( ) . job ( "Mythbusters" ) . job ( "Unchained Reaction" ) . build ( ) ; приведёт к тому, что List jobs поле будет иметь две строки. Для этого к полю/параметру должна быть добавлена аннотация @Singular.

Теперь когда со статическим методом всё понятно, указание аннотации @Builder для конструктора работает так же. Фактически конструкторы — это просто статические методы, имеющие особый синтаксис для их вызова. Их возвращаемый тип — это класс, который они создают, а их параметры те же, что и параметры класса.

В конечном итоге применение @Builder к классу — это то же самое, что и добавление @AllArgsConstructor(access = AccessLevel.PACKAGE) к классу и применение аннотации @Builder к этому all-args-конструктору. Это работает, только если вы не писали явных конструкторов. Если уже есть явный конструктор, то добавляйте аннотацию @Builder к этому конструктору, а не к классу.

Если вы используете @Builder для генерации builder-ов, создающих экземпляры вашего класса (это обычно так и есть, если вы не используете @Builder для статического метода, который не возвращает ваш тип), вы можете использовать @Builder ( toBuilder = true ) для генерации метода экземпляров вашего класса toBuilder(). Он создаёт новый builder, который уже содержит все значения из текущего экземпляра. Вы можете добавить @Builder.ObtainVia к параметрам (в случае использования конструктора или статического метода) или полям (в случае @Builder для типа), для указания альтернативного способа, которым значения этих полей/параметров получаются из экземпляра. Например, вы можете указать выполнение метода: @Builder . ObtainVia ( method = "calculateFoo" ) .

Имя класса builder-а — FoobarBuilder, где Foobar — это упрощённая, начинающаяся с заглавной буквы форма цели, то есть это имя вашего класса при использовании @Builder для конструкторов или типов, и это имя возвращаемого типа при использовании для статических методов.Например, если аннотация @Builder применена для класса с именем com.yoyodyne.FancyList, то имя builder-а будет FancyListBuilder. Если @Builder применён к статическому методу, возвращающему void, то класс будет с именем VoidBuilder.

Настраиваемые части builder-а:

  • Имя класса builder-а (по умолчанию: return type + 'Builder' )
  • Имя метода build() (по умолчанию: "build" )
  • Имя метода builder() (по умолчанию: "builder" )
  • Нужен ли toBuilder() (по умолчанию: нет)

Пример использования, где все настройки отличны от значений по умолчанию:

Эти три аннотации генерируют конструктор, который принимает 1 параметр для определённых полей и просто присваивает этот параметр полю.

@NoArgsConstructor генерирует конструктор без параметров. Если это невозможно (потому что поля final), то возникает ошибка компиляции. Если используется @NoArgsConstructor(force = true), то все final поля инициализируются 0 / false / null. Для полей с ограничениями, например @NotNull, никаких проверок при присвоении не генерируется, поэтому эти условия могут не выполняться, пока эти поля не будут инициализированы подобающим образом позже. Определённые Java-конструкции, например Hibernate и Service Provider Interface требуют наличия конструктора без аргументов. Эта конструкция используется главным образом вместе с @Data или одной из других аннотаций, генерирующих конструктор.

@RequiredArgsConstructor генерирует конструктор с 1 параметром для каждого поля, которое требует специальной обработки. Все неинициализированные final поля получают параметр, также как все остальные поля, помеченные @NonNull, которые не иницилизированы при объявлении. Для этих случаев также генерируется явная проверка на null. Конструктор бросает исключение NullPointerException, если какой-либо из параметров, предназначенный для полей, помеченных @NonNull содержит null. Порядок этих параметров совпадает с порядком появления полей в классе.

@AllArgsConstructor генерирует конструктор с одним параметром для каждого поля в классе. Поля, помеченные @NonNull, имеют проверку на null для этих параметров.

Каждая из этих аннотаций имеет альтернативную форму, где сгенерированный конструктор всегда приватный, и генерируется дополнительный статический фабричный метод, оборачивающий этот конструктор. Этот режим включается с помощью параметра staticName в аннотации, например: @ RequiredArgsConstructor ( staticName = "of" ) . Такой статический метод выводит шаблоны в отличие от нормального конструктора. Это означает, что пользователи вашего API смогут писать MapEntry . of ( "foo" , 5 ) , вместо new MapEntry < String , Integer >( "foo" , 5 ) .

Для того чтобы добавить аннотации к сгенерированным конструкторам, вы можете использовать onConstructor = @__ ( < @AnnotationsHere >) , но будьте осторожны, так как это экспериментальная возможность.

Статические поля пропускаются этими аннотациями. Также аннотация @java.beans.ConstructorProperties добавляется ко всем конструкторам, у которых хотя бы один аргумент, что позволяет утилитам редактирования вызывать сгенерированные конструкторы. @ConstructorProperties сейчас находится в Java 1.6, что означает, что если ваш код будет компилироваться в Java 1.5, то возникнет ошибка компиляции. Запуск на JVM 1.5 должен проходить без проблем (аннотация игнорируется). Чтобы подавить генерацию аннотации @ConstructorProperties, добавьте параметр к вашим аннотациям: @AllArgsConstructor ( suppressConstructorProperties = true ) . Однако как только Java 1.5, время время которой уже прошло, уйдёт в забвение, этот параметр будет удалён. Поэтому он помечен как устаревший.

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

@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 ) ; .

Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.

Overview

This set of 3 annotations generate a constructor that will accept 1 parameter for certain fields, and simply assigns this parameter to the field.

@NoArgsConstructor will generate a constructor with no parameters. If this is not possible (because of final fields), a compiler error will result instead, unless @NoArgsConstructor(force = true) is used, then all final fields are initialized with 0 / false / null . For fields with constraints, such as @NonNull fields, no check is generated,so be aware that these constraints will generally not be fulfilled until those fields are properly initialized later. Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor. This annotation is useful primarily in combination with either @Data or one of the other constructor generating annotations.

@RequiredArgsConstructor generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final fields get a parameter, as well as any fields that are marked as @NonNull that aren't initialized where they are declared. For those fields marked with @NonNull , an explicit null check is also generated. The constructor will throw a NullPointerException if any of the parameters intended for the fields marked with @NonNull contain null . The order of the parameters match the order in which the fields appear in your class.

@AllArgsConstructor generates a constructor with 1 parameter for each field in your class. Fields marked with @NonNull result in null checks on those parameters.

Each of these annotations allows an alternate form, where the generated constructor is always private, and an additional static factory method that wraps around the private constructor is generated. This mode is enabled by supplying the staticName value for the annotation, like so: @RequiredArgsConstructor(staticName="of") . Such a static factory method will infer generics, unlike a normal constructor. This means your API users get write MapEntry.of("foo", 5) instead of the much longer new MapEntry("foo", 5) .

To put annotations on the generated constructor, you can use onConstructor=@__() , but be careful; this is an experimental feature. For more details see the documentation on the onX feature.

Static fields are skipped by these annotations.

Unlike most other lombok annotations, the existence of an explicit constructor does not stop these annotations from generating their own constructor. This means you can write your own specialized constructor, and let lombok generate the boilerplate ones as well. If a conflict arises (one of your constructors ends up with the same signature as one that lombok generates), a compiler error will occur.

With Lombok

Vanilla Java

Supported configuration keys:

lombok.anyConstructor.addConstructorProperties = [ true | false ] (default: false ) If set to true , then lombok will add a @java.beans.ConstructorProperties to generated constructors. lombok. [ allArgsConstructor | requiredArgsConstructor | noArgsConstructor ] .flagUsage = [ warning | error ] (default: not set) Lombok will flag any usage of the relevant annotation ( @AllArgsConstructor , @RequiredArgsConstructor or @NoArgsConstructor ) as a warning or error if configured. lombok.anyConstructor.flagUsage = [ warning | error ] (default: not set) Lombok will flag any usage of any of the 3 constructor-generating annotations as a warning or error if configured. lombok.copyableAnnotations = [A list of fully qualified types] (default: empty list) Lombok will copy any of these annotations from the field to the constructor parameter, the setter parameter, and the getter method. Note that lombok ships with a bunch of annotations 'out of the box' which are known to be copyable: All popular nullable/nonnull annotations. lombok.noArgsConstructor.extraPrivate = [ true | false ] (default: false) If true , lombok will generate a private no-args constructor for any @Value or @Data annotated class, which sets all fields to default values (null / 0 / false).

Small print

Even if a field is explicitly initialized with null , lombok will consider the requirement to avoid null as fulfilled, and will NOT consider the field as a 'required' argument. The assumption is that if you explicitly assign null to a field that you've also marked as @NonNull signals you must know what you're doing.

The @java.beans.ConstructorProperties annotation is never generated for a constructor with no arguments. This also explains why @NoArgsConstructor lacks the suppressConstructorProperties annotation method. The generated static factory methods also do not get @ConstructorProperties , as this annotation can only be added to real constructors.

@XArgsConstructor can also be used on an enum definition. The generated constructor will always be private, because non-private constructors aren't legal in enums. You don't have to specify AccessLevel.PRIVATE .

Various well known annotations about nullity cause null checks to be inserted and will be copied to the parameter. See Getter/Setter documentation's small print for more information.

The flagUsage configuration keys do not trigger when a constructor is generated by @Data , @Value or any other lombok annotation.

Читайте также: