@Builder will ignore the initializing expression entirely 경고 해결

2023. 11. 1. 11:47Project 해축갤/에러 해결

728x90
.../entity/Member.java:33: warning: @Builder will ignore the initializing expression entirely. 

If you want the initializing expression to serve as default, add @Builder.Default. 

If it is not supposed to be settable during building, make the field final.

private List<Post> posts = new ArrayList<>();

빌드를 하던 와중에 이런 경고가 나왔습니다.

Builder는 초기화 식을 아얘 무시한다는 경고문입니다.

원인

Member 엔티티

저의 Member 엔티티입니다.

여기서 경고를 일으키는 문제점은 posts, comments입니다.

Builder 가 두 필드에 default 값으로 매긴 new ArrayList <>()를 무시한다는 경고인 거죠.

이전에 제가 엔티티에다 setter를 사용하지 않으려고

@Builder를 사용했었습니다.

MemberService 의 멤버 등록 메서드

하지만 되려 이게 경고를 발생시키는 문제가 된 거죠.

급하니 일단 해결 방안부터

해결 방안은 간단합니다

@Builder.Default

초기화를 원하는 필드에다가 @Builder. Default를 붙이는 것입니다.

이렇게 하게 되면, Builder 패턴 사용 시 할당을 하지 않아도

자동으로 지정한 초기화 식을 적용 한다는 것입니다.

@Builder.@Default 의 설명

The field annotated with @Default must have an initializing expression;
that expression is taken as the default to be used if not explicitly set during building

즉, @Default 애노테이션을 가진 필드는 

  1. 반드시 초기화 식을 가져야 하고
  2. building 과정 시에 초기화되지 않으면, 식대로 초기화가 된다

라는 것입니다.

 

그래서 위처럼 @Builder. Default 애노테이션을 달면 해결이 되는 거죠.

 

자 급한 불 껐으니, 진짜 가볍게 원리를 배우러

자 급한 불은 끄셨을 거라고 봅니다!

사실 에러가 좀 급하긴 해~

어째서 Builder 가 무시하는지 가벼운 예제로 한번 알아보죠.

 

@Builder는 자동으로 빌더 패턴을 생성해 주는 어노테이션이에요.

Java에서 빌더 패턴은 객체 생성 시 다양한 파라미터를 효과적으로 다루기 위해 사용되는 패턴 중 하나입니다.

 

클래스 필드의 초기화식은 클래스의 인스턴스가 생성될 해당 필드에 값을 할당하는 코드입니다.

 

그런데, @Builder 해당 클래스의 별도의 static 내부 클래스를 만들어서 빌더 패턴을 구현합니다.

내부 클래스는 원래 클래스의 필드 초기화식에 접근할 없기 때문에 초기화식을 무시하게 됩니다.

 

예를 들어 다음과 같은 클래스가 있다고 해보죠.

@Builder
public class Sample {
    private String name = "name";
    private int age = 12;
    private boolean active = true;
}

그렇다면 Lombok 은 대략 다음과 같은 코드를 주입하게 됩니다.

public class Sample {
    private String name = "name";
    private int age = 12;
    private boolean active = true;

    public static class SampleBuilder {
        private String name;
        private int age;
        private boolean active;

        SampleBuilder() {
        }

        public SampleBuilder name(String name) {
            this.name = name;
            return this;
        }

        public SampleBuilder age(int age) {
            this.age = age;
            return this;
        }

        public SampleBuilder active(boolean active) {
            this.active = active;
            return this;
        }

        public Sample build() {
            Sample sample = new Sample();
            sample.name = this.name;
            sample.age = this.age;
            sample.active = this.active;
            return sample;
        }
    }

    // ... 다른 메서드들
}

결국 우리는 build를 통해서 Sample 객체를 만들어낼 건데,

Sample 객체의 필드에 할당하는 것은 내부 SampleBuilder 클래스의 필드값을 할당받게 됩니다.

 

즉, 우리가 default 값을 넣는다고 해도 null로 재할당이 되는 거죠.

 

결론

즉, 우리가 이렇게 @Builder 사용 시에 default 값을 원하면

꼭 @Builder. Default를 사용해 주자!

728x90