Почему аннотация @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 в одну строчку
Что значит 'synchronized'?
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?