[trouble shooting] constructor cannot be applied to given types / @Builder & @NoArgsConstructor

2023. 1. 4. 01:26BACKEND/TROUBLE SHOOTING

 

 

 

 

 

문제

@Builer와 @NoArgsConstructor를 같이 쓰면 에러가 발생한다.

 

해결

@NoArgsConstructor 를 쓰고 클래스 레벨의 @Builder를 쓰게 되면 @AllArgsConstructor 없이 기본 생성자만 선언한 것과 같으므로 컴파일 에러가 뜬다.

 

설명

Lombok에서 제공하는 @Builder는 생성자 인자를 메서드 체인을 통해 명시적으로 대딥하여 생성자 호출할 수 있게 해준다. 생성자, 메서드, 클래스 레벨에서 쓰일 수 있고, 클래스 레벨에서 쓰일 경우 기본적으로 전체 멤버를 생성자의 매개값으로 갖는 private 생성자를 만든다. @Builder 를 붙이면 Lombok 빌더에서 해당 생성자를 바탕으로 빌더 패턴을 생성한다. 다시 말해서 Lombok의 @Builder는 기본적으로 모든 매개변수를 받는 생성자(@AllArgsConstructor)를 빌더에 사용한다는 뜻이다. @Builer를 적용하는 것은 @AllArgsConstructor(access = AccessLevel.PACKAGE)를 추가한 것과 같은 효과를 보인다.

단, 클래스 내에 특정 생성자가 있다면 암묵적으로 @AllArgsConstructor를 하지 않는다. 이 생성자는 @NoArgsConstructor, @RequiredArgsConstructor 또는 어떤 생성자도 클래스 내부에 선언하지 않았을 경우에만 생성된다. 따라서 이 경우 @AllArgsConstructor가 없으면 컴파일 에러가 발생하고 @Builder를 클래스 레벨에서 쓰려면 @AllArgsConstructor가 있어야 한다. 이 외의 생성자는 컴파일 에러를 발생시킨다. 따라서 기본 생성자(@NoArgsConstructor)만 정의하고 @Builder를 사용한다면 모든 매개변수를 받는 생성자를 호출하는데 만들어지지 않았으므로 @AllArgsConstructor 추가하지 않았으므로 에러가 발생한다. 그래서 간편하게 하기 위해 @AllArgsConstructor를 함께 사용하거나 특정 생성자 정의 후 그 위에 @Builder를 붙여주어 해결한다.

그런데 JPA나 json parser와 같은 라이브러리를 쓸 때에는 반드시 클래스에 기본 생성자가 있어야 한다. 이 경우 @NoArgsConstructor를 쓸 수 밖에 없다. 그러면 클래스 레벨에서 @Builder를 쓸 수가 없어진다. 방법은 전체 필드를 사용하는 생성자를 직접 선언하고 그 생성자에 @Builder 어노테이션을 쓰든가, 아니면 @NoArgsConstructor 와 @AllArgsConstructor를 모두 쓰면 된다.

결론적으로 @Builder를 클래스 레벨에서 쓰면 모든 필드로 생성자를 생성하는 빌더를 생성하는데 이 때 모든 필드 생성자가 선언되어 있어야 하기 때문에 생성자 없이 다른 생성자를 오버로딩 하면 컴파일 에러가 발생한다.

 

공식문서

Finally, applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself.

@Builder (projectlombok.org)

 

@Builder

 

projectlombok.org

 

 

참고자료

[오류] Lombok @Builder 생성자 .. : 네이버블로그 (naver.com)

 

[오류] Lombok @Builder 생성자 관련 오류

롬복의 @Builder 사용시 생성자 관련 오류를 은근히 자주 접한다. 그래서 이참에 오류를 정리해서 다음에...

blog.naver.com