@Data
@Data는 @Getter, @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode을 한꺼번에 설정해주는 매우 유용한 어노테이션입니다.
@Data
public class User {
// ...
}
사용 방법은 다른 어노테이션들과 대동소이합니다. 클래스 레벨에서 @Data 어노테이션을 붙여주면, 모든 필드를 대상으로 접근자와 설정자가 자동으로 생성되고, final 또는 @NonNull 필드 값을 파라미터로 받는 생성자가 만들어지며, toStirng, equals, hashCode 메소드가 자동으로 만들어집니다.
@Builder 어노테이션
만일 이 어노테이션이 없었다면 After 부분을 일일이 직접 구현해줘야했다.
// Before:
@Builder
class Example<T> {
private T foo;
private final String bar;
}
// After:
class Example<T> {
private T foo;
private final String bar;
private Example(T foo, String bar) {
this.foo = foo;
this.bar = bar;
}
public static <T> ExampleBuilder<T> builder() {
return new ExampleBuilder<T>();
}
public static class ExampleBuilder<T> {
private T foo;
private String bar;
private ExampleBuilder() {}
public ExampleBuilder foo(T foo) {
this.foo = foo;
return this;
}
public ExampleBuilder bar(String bar) {
this.bar = bar;
return this;
}
@java.lang.Override public String toString() {
return "ExampleBuilder(foo = " + foo + ", bar = " + bar + ")";
}
public Example build() {
return new Example(foo, bar);
}
}
}
사용법은 아주 간단하다. 빌더 패턴을 적용할 객체에 @Builder 어노테이션을 달기만 하면된다.
@Builder
public class Bag {
private String name;
private int money;
private STring memo;
}
어노테이션만 달면 빌더가 생기고 위에 썼던 것과 같이 빌더를 통해 객체를 생성할 수 있다.
Bag bag = Bag.builder()
.name("name")
.money(1000)
.memo("memo")
.build();
@Builder 어노테이션 옵션
builderMethodName
@Builder 어노테이션을 사용하면 빌더를 생성하는 메서드의 이름은 기본 값인 builder()이다. 이를 새롭게 네이밍 할 수 있는 어노테이션 값이다.
이 객체를 사용하고자 하는 사람에게 도움이 되는 방향으로 빌더 메서드 이름을 정의하자. 보통은 기본 값인 builder()를 그대로 사용한다.
Bag bag = Bag.builder()
...
buildMethodName
builder()로 얻은 빌더에 필드 값들을 입력하고 마지막에 객체를 생성하는 동작인 빌드 메서드의 이름을 네이밍 할 수 있는 어노테이션 값이다.
기본 값은 build()로 create() 등 필요한대로 네이밍하면 된다. 이에 맞춰서 빌더 메소드도 같이 리네이밍해주기도 한다.
Bag bag = Bag.builder()
.build();
toBuilder
boolean 값으로 설정할 수 있는 어노테이션 값으로 기본 값은 false이다. 이 값을 true로 설정시 빌더로 만든 인스턴스에서 toBuilder() 메서드를 호출해 그 인스턴스 값을 베이스로 빌더 패턴으로 새로운 인스턴스를 생성할 수 있다.
기본 값인 false로 설정할 경우 toBuilder() 메서드 자체가 존재하지 않는 메서드라는 에러가 발생한다.
Bag bag1 = Bag.builder()
.name("name")
.money(1000)
.memo("memo")
.build();
Bag bag2 = bag1.toBuilder().money(8000).build();
access()
builder 클래스의 접근제어자를 어떻게 할 것인지에 대한 설정 값이다. 기본은 public으로 되어 있다.
AccessLevel access() default lombok.AccessLevel.PUBLIC;
접근자/설정자 자동 생성 (@Getter, @Setter)
제일 먼저 살펴볼 어노테이션은 @Getter와 @Setter 입니다. 아마 Lombok에서 가장 많이 사용되는 어노테이션일 텐데요. 예를 들어, xxx라는 필드에 선언하면 자동으로 getXxx()(boolean 타입인 경우, isXxx())와 setXxx() 메소드를 생성해줍니다.
@Getter @Setter
private String name;
위와 같이 특정 필드에 어노테이션을 붙여주면, 다음과 같이 자동으로 생성된 접근자와 설정자 메소드를 사용할 수 있어서 매우 편리합니다.
user.setName("홍길동");
String userName = user.getName();
또한, 필드 레벨이 아닌 클래스 레벨에 @Getter 또는 @Setter를 선언해줄 경우, 모든 필드에 접근자와 설정자가 자동으로 생성됩니다.
VO 클래스를 작성할 때 마다, 접근자와 설정자 메소드를 작성해주는게 참 번거로운 일이었는데, (특히, 수정할 때는 더욱이) Lombok을 쓰게되면 이런 노가다성 코딩에서 해방될 수 있습니다. :)
생성자 자동 생성 ( @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor)
Lombok을 사용하면 생성자도 자동으로 생성할 수 있습니다. @NoArgsConstructor 어노테이션은 파라미터가 없는 기본 생성자를 생성해주고, @AllArgsConstructor 어노테이션은 모든 필드 값을 파라미터로 받는 생성자를 만들어줍니다. 마지막으로 @RequiredArgsConstructor 어노테이션은 final이나 @NonNull인 필드 값만 파라미터로 받는 생성자를 만들어줍니다.
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
@NonNull
private String username;
@NonNull
private String password;
private int[] scores;
}
User user1 = new User();
User user2 = new User("dale", "1234");
User user3 = new User(1L, "dale", "1234", null);
ToString 메소드 자동 생성(@ToString)
toString() 메소드를 작성하는 것도 여간 귀찮은 일이 아닙니다. 하지만 Lombok을 사용하면 @ToString 어노테이션만 클래스에 붙여주면 자동으로 생성해줍니다.
예제와 같이 exclude 속성을 사용하면, 특정 필드를 toString() 결과에서 제외시킬 수도 있습니다.
@ToString(exclude = "password")
public class User {
private Long id;
private String username;
private String password;
private int[] scores;
}
위와 같이 클래스에 @ToString 어노테이션을 붙이고, 아래와 같이 필드를 세팅 후 출력을 하면,
User user = new User();
user.setId(1L);
user.setUsername("dale");
user.setUsername("1234");
user.setScores(new int[]{80, 70, 100});
System.out.println(user);
다음과 같이, 클래스명(필드1명=필드1값,필드2명=필드2값,...) 식으로 출력됩니다.
User(id=1, username=1234, scores=[80, 70, 100])
Lombok을 사용하기 전에는 Apache Commons Lang 라이브러리의 ToStringBuilder를 사용했었는데, Lombok을 사용하는 게 어노테이션 한 방으로 끝나니 훨씬 편한 것 같습니다.
equals, hashCode 자동 생성 (@EqualsAndHashCode)
자바 빈을 만들 때 equals와 hashCode 메소드를 자주 오버라이딩 하는데요. @EqualsAndHashCode 어노테이션을 사용하면 자동으로 이 메소드를 생성할 수 있습니다.
- equals : 두 객체의 내용이 같은지, 동등성(equality) 를 비교하는 연산자
- 같은 객체인지 확인하는 메소드는 equals()이다.
- hashCode : 두 객체가 같은 객체인지, 동일성(identity) 를 비교하는 연산자
- 두 객체의 내부의 값이 같은지 숫자로 확인하는 값은 hashcode()이다
@EqualsAndHashCode(callSuper = true)
public class User extends Domain {
private String username;
private String password;
}
callSuper 속성을 통해 equals와 hashCode 메소드 자동 생성 시 부모 클래스의 필드까지 감안할지 안 할지에 대해서 설정할 수 있습니다.
즉, callSuper = true로 설정하면 부모 클래스 필드 값들도 동일한지 체크하며, callSuper = false로 설정(기본값)하면 자신 클래스의 필드 값들만 고려합니다.
User user1 = new User();
user1.setId(1L);
user1.setUsername("user");
user1.setPassword("pass");
User user2 = new User();
user1.setId(2L); // 부모 클래스의 필드가 다름
user2.setUsername("user");
user2.setPassword("pass");
user1.equals(user2);
// callSuper = true 이면 false, callSuper = false 이면 true
연관된 글 :
[Spring] @RequestBody / @ResponseBody 어노테이션 이란?
[Spring] 빌더 패턴(Bulider Pattern)
참고:
[JAVA] Lombok @Getter, @Setter, @EqualsAndHashCode, @Data 자주쓰이는 어노테이션들
Lombok @Data의 @EqualsAndHashCode이 뭐하는 애일까?
@Data, @EqualsAndHashCode 어노테이션
'개발 > Java' 카테고리의 다른 글
[Java] Stream API - map과 flatMap (1) | 2024.06.06 |
---|---|
[JAVA] DTO, VO, DAO, Entity 의 차이 (0) | 2023.05.25 |
[Java] Interface (0) | 2023.04.01 |
[Java] 멀티 스레드(multi thread) (0) | 2023.03.29 |
[Java] 메소드 참조(method reference) (0) | 2023.03.20 |