Почему аннотация @Builder из Lombok несовместима с этим конструктором?
У меня есть такой простой код:
@Data
@Builder
public class RegistrationInfo {
private String mail;
private String password;
public RegistrationInfo(RegistrationInfo registrationInfo) {
this.mail = registrationInfo.mail;
this.password = registrationInfo.password;
}
}
Сначала я использовал только аннотацию @Builder
от Lombok, и всё работало нормально. Но после того, как я добавил конструктор, код перестал компилироваться. Ошибка следующая:
Error:(2, 1) java: constructor RegistrationInfo in class com.user.RegistrationInfo cannot be applied to given types;
required: com.user.RegistrationInfo
found: java.lang.String,java.lang.String
reason: actual and formal argument lists differ in length
У меня есть два вопроса:
- Почему аннотация Lombok
@Builder
не совместима с этим конструктором? - Как сделать так, чтобы код компилировался, учитывая, что мне нужны и билдера, и конструктор?
3 ответ(ов)
Вы можете либо использовать аннотацию @AllArgsConstructor
, потому что
@Builder
генерирует конструктор с параметрами, если не определены другие конструкторы.(Цитируя @Andrew Tobilko)
Либо установить атрибут у @Builder
: @Builder(toBuilder = true)
. Это даст вам функциональность конструктора копирования.
@Builder(toBuilder = true)
class Foo {
// поля и т.д.
}
Foo foo = getReferenceToFooInstance();
Foo copy = foo.toBuilder().build();
Таким образом, если вам нужно создать копию объекта, добавьте toBuilder = true
и используйте метод toBuilder()
.
Когда вы предоставляете свой собственный конструктор, Lombok не создает конструктор с параметрами, который используется аннотацией @Builder
. Поэтому вам нужно просто добавить аннотацию @AllArgsConstructor
к вашему классу:
@Data // старайтесь избегать этой аннотации, так как она считается антипаттерном
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RegistrationInfo {
//...
}
Таким образом, вы получите доступ к конструктору с параметрами и возможность использовать @Builder
без проблем.
В данном примере использование аннотации @Builder
в сочетании с явным определением конструктора может вызывать некоторые вопросы. Давайте разберем это подробнее.
Когда вы используете аннотацию @Builder
в классе, она действительно генерирует билдер с полями класса. Однако, в вашем коде есть также аннотация @AllArgsConstructor(access = AccessLevel.PRIVATE)
, которая указывает на то, что должен быть сгенерирован конструктор с аргументами для всех полей, но с приватным уровнем доступа.
Ваша реализация конструктора private RegistrationInfo(RegistrationInfo registrationInfo)
является дополнительным частным конструктором, который принимает объект RegistrationInfo
и, вероятно, предназначен для выполнения определенной логики копирования.
Таким образом, если в классе не определены дополнительные конструкторы, то @Builder
действительно будет генерировать конструктор с фиксированными параметрами для всех полей. Однако в вашем случае наличие конструктора с параметром RegistrationInfo
и конструктора с @AllArgsConstructor
может привести к тому, что поведение @Builder
будет отличаться.
Итак, в общем случае, если нет определенных других конструкторов, то возможно, что @Builder
создаст конструктор со всеми аргументами, даже если вы используете @AllArgsConstructor
. Но так как у вас есть несколько специально определенных конструкторов, необходимо проверять, как будет работать билдер в результате.
Для лучшего понимания работы этих аннотаций посмотрите также документацию Lombok и убедитесь, что вы разберетесь, как именно они взаимодействуют между собой в вашем контексте.
Инициализация ArrayList в одну строчку
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Что такое «сырые типы» и почему их не следует использовать?
Создание репозитория Spring без сущности
Как сгенерировать уникальный хеш-код для строкового ввода в Android?