본문 바로가기
Programing/Java

Lombok @Builder 사용시 기본값 지정하기

by Tomining 2017. 4. 12.
Lombok이 무엇인지 간단히 살펴보고 넘어가자. 어떻게 프로젝트에 적용하는지는 언급하지 않는다. 검색을 통해서 알아보자.

가장 기본적인 기능으로 Lombok은 getter/setter method를 만들어 준다.
예를 들어 아래와 같이 User라는 모델 객체가 있다고 가정하자.
public class User {
  private String name;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}
@Data
public class User {
  private String name;
  private int age;
}
Lombok을 적용하면 우측 코드처럼 간단히 모델 객체를 선언할 수 있다.

@Builder

Lombok에는 @Builder Annotation도 있다. 이는 모델 객체를 생성할 때 Builder를 자동으로 추가해 주는 Annotation이다. 이를 이용하면 Builder Pattern을 아주 손쉽게 적용할 수 있다.
아래 예제를 살펴보자.
public class User {
  private String name;
  private int age;

  public static UserBuilder builder() {
    return new UserBuilder();
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

//Builder Class
public class UserBuilder {
  private String name;
  private int age;

  public User build() {
    User user = new User();
    user.setName(this.name);
    user.setAge(this.age);
    return user;
  }

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

  public UserBuilder age(int age) {
    this.age = age;
    return this;
  }
}
@Data
@Builder
public class User {
  private String name;
  private int age;
}
public class UserBuilderTest {
  @Test  public void builderTest() {
    User user = User.builder()
                  .name("홍길동")
                  .age(19)
                  .build();
    System.out.println(user);
  }
}
public class UserBuilderTest {
  @Test  public void builderTest() {
    User user = User.builder()
                  .name("홍길동")
                  .age(19)
                  .build();
    System.out.println(user);
  }
}
우측 코드는 Lombok의 Builder를 적용한 코드이다.
코드를 확 줄여준 것을 볼 수 있다.

@Builder 사용시 특정 속성에 기본값을 설정하려면???

이 글을 쓰게된 주된 목적은 여기부터이다.
@Data@Builderpublic class User {
  private String name;
  private int age = 19;
}
public class UserBuilderTest {
  @Test  public void builderTest() {
    User user = User.builder()
                  .name("홍길동")
                  .build();
    System.out.println(user);
  }
}
테스트 코드에서 user.getAge()는 19일 것으로 기대했다.
하지만 결과는…



왜 그럴까? 어떻게 age에 19라는 기본값을 지정할 수 있을까?
구글링을 해보니 기본 생성자(default constructor)를 만들어 기본값을 지정하라는 코맨트가 많았다.
Lombok을 사용하는데, 기본 생성자를 매번 생성해 하고 싶지 않아 좀 더 찾아보기로 했다.

결론은 1.16.16 버전 이상을 사용하면 @Builder.Default 라는 Annotation이 추가 되었다.
(불행히도 위 궁금증을 가질 때 1.16.6 버전을 사용하고 있었다.)
Lombok을 1.16.16으로 업그레이드 이후 테스트를 해 보았다.
@Data@Builderpublic class User {
  private String name;
  @Builder.Default  private int age = 19;
}
public class UserBuilderTest {
  @Test  public void builderTest() {
    User user = User.builder()
                  .name("홍길동")
                  .build();
    System.out.println(user);
  }
}


이제 정상적으로 age에 19라는 값이 설정되는 것을 확인할 수 있다.

그렇다면 Lombok 1.16.16 이전 버전에서는 기본값이 적용되지 않았을까?
Lombok 공신문서에서 @Builder.Default에 대해서 아래와 같이 설명하고 있다.

@Builder.Default

If a certain field/parameter is never set during a build session, then it always gets 0 / null / false. If you've put @Builder on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with @Builder.Default:
@Builder.Default private final long created = System.currentTimeMillis();
즉, @Builder를 사용한 경우 build()시 설정하지 않으면 0 / null / false가 된다고 언급하고 있다.
위 테스트 코드에서 getAge() 했을 때, 0이 나온 이유이다.

결론

Lombok의 @Data, @Builder를 적극적으로 사용하자. 개발의 편의성을 위해…
그리고 특정 속성에 기본값을 지정하고 싶을 때에는 @Builder.Default를 사용하자.(단 Lombok 1.16.16 이상)
현재 최신 버전이 1.16.16이다.(at 2017/04/12)

참고