객체를 클래스로 정의할 때, 자주 등장하는 녀석이다.
여러 기능들을 포함하고 있는 간편한 기능인데, 사용 시 주의해야 할 사항도 있으니 함께 알아보려고 한다.
아래 글과 블로그를 참고했다.
- @Value
Overview
@Value 어노테이션은 @Data 어노테이션의 변형된 녀석인데, 특이한 점은 객체를 불변(Immutable)으로 만들어준다는 점이다.
여기서 불변(Immutable)이란, 객체 생성 후 그 상태를 수정할 수 없는 것을 뜻한다.
그렇기 때문에 객체의 상태를 변경할 수 있는 @Setter는 생성되지 않는다.
(@Setter, @Getter는 요즘 Spring 개발자치고 모르는 사람이 없을 정도로 기초적인 어노테이션이기 때문에 이 글에서는 굳이 설명하지 않겠다)
그리고 default 값으로, 객체 내부의 모든 field에 private과 final을 붙여준다.
field 뿐만 아니라 class에도 final을 디폴트 값으로 붙여주는데, 위에서 언급했듯이 객체를 불변(Immutable)으로 만들어주는 기능을 하기 때문이다.
이러한 불변성(Immutability) 때문에 자식 클래스(subclass)를 가질 수 없게 된다.
또한 @Data 어노테이션의 변형이기 때문에, 마찬가지로 유용하게 쓰일 수 있는 toString(), equals() 및 hashCode() 메소드도 자동 생성되며,
각 field의 getter 메소드 또한 자동 생성되고,
모든 argument를 포함하는 생성자(단, field 선언 시 초기화되는 final fields는 제외)도 자동 생성된다.
위와 같은 특성들 때문에, @Value는 아래 다섯 개의 어노테이션을 합친 약어라고 할 수 있다.
단, 아래에서 소개할 어노테이션들 중 관련된 메소드들을 직접 정의해도 warning이나 error는 발생하지 않고, 해당 어노테이션이 구현하는 메소드는 생성되지 않는다.
예를 들어, toString() 메소드를 직접 정의해도 괜찮고, @AllArgsConstructor 어노테이션이 @Value에 포함되어 있지만 클래스에 작성해줘도 괜찮다.
추가로, @Builder와 @Value가 클래스에 같이 붙어 있다면, @Value가 만드는 public allargs constructor 보다 @Builder가 만드는 private allargs constructor 가 우선순위가 높아, @Builder가 만드는 생성자가 생성된다.
1. @ToString
@ToString 공식 문서에 따르면,
이 어노테이션이 붙어있는 클래스는 lombok이 toString() 메소드를 자동으로 생성한다.
toString() 메소드도 워낙 유명하지만 간단히 짚고 넘어가자면,
Java의 모든 객체는java.lang.Object라는 최상위 부모 클래스를 상속받는데, 이 Object 클래스 안에는 아래와 같은 toString() 메소드가 있다.
public String toString() {
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
객체에 대한 정보를 String으로 변환해주는 메소드이지만, 보다시피 객체의 이름과 hash code 값의 정보만 준다.
이 두 정보들로는 큰 의미가 없기 때문에 보통 Overriding 하여 프로그래머 입맛에 맞춰 커스터마이징을 하곤 했는데,
이 어노테이션을 사용하면, MyClass(foo=123, bar=234)와 같은 형태로 출력되는 toString() 메소드를 자동으로 만들어준다.
(class 이름이 먼저 나타나고 뒤에 괄호가 나타나며 콤마로 필드들이 구분되는 이 출력 형태는 고정되어 있어 바꿀 수 없다)
하지만 만약 이 쓸모없는 정보를 굳이 원한다면,
default 값이 false인 callSuper라는 옵션에 true 값을 주어 부모 클래스(Object 클래스)에 구현되어 있는, 위처럼 생긴 toString() 메소드의 출력 값을 얻어올 수 있긴 하다.
default 값이 true인 includeFieldNames라는 옵션에 true 값을 주어 표현의 명료성을 나타내며, toString() 메소드의 출력 값에 field 명이 나타나도록 할 수 있기도 하다(하지만 어노테이션 길이가 길어지는 단점이 존재..).
default 값으로 static이 아닌 모든 fields가 출력된다.
만약 특정 fields는 출력하기 싫다면, 해당 field들에 @ToString. Exclude라는 어노테이션을 주면 된다.
혹은 클래스에 @ToString(onlyExplicitlyIncluded = true)처럼 옵션을 주고, 출력되기 원하는 field에 @ToString. Include라는 어노테이션을 주는 방법도 있다.
이 @ToString.Include 어노테이션의 name이라는 옵션을 사용하면 해당 field 명을 다르게 출력할 수 있는데, @ToString.Include(name = "some other name")처럼 사용하면 된다.
또한 field들이 출력되는 순서 또한 rank라는 옵션을 통해 바꿀 수 있는데, @ToString.Include(rank = -1)처럼 사용하면 된다.
이 rank 옵션이 없는 field의 default rank 값은 0이며, rank 값이 높은(숫자가 작은) 순서대로 출력되며, 같은 rank 값이라면 field가 선언된 순서대로 나타난다.
2. @EqualsAndHashCode
(이 어노테이션은 추후 자세히 다뤄볼 생각이 있기 때문에 가볍게만 짚고 넘어가려고 한다)
@EqualsAndHashCode 공식 문서에 따르면,
이 어노테이션이 붙어있는 클래스는 lombok이 equals(Object other)과 hashCode() 메소드를 자동으로 생성한다.
equals(Object other)은 두 객체의 내용이 같은지, 동등성(equality)을 비교하는 메소드이고,
hashCode()는 두 객체가 같은 객체인지, 동일성(identity)을 비교하는 메소드이다.
3. @AllArgsConstructor
이전에 작성한 글 참고!
4. @FieldDefaults(makeFinal = true, level = AccessLevel.Private)
@FieldDefaults 공식 문서에 따르면,
class나 enum에 이 어노테이션이 붙어있으면, 내부의 각 field마다 접근 제어자(access modifier)와 final 키워드를 자동으로 추가한다.
먼저, 모든 field에 접근 제어자를 붙여주려면 level이라는 옵션의 값에 원하는 접근 제어자를 적어주면 된다.
예를 들어, 모든 field를 private로 만들려면 @FieldDefaults(level = AccessLevel.Private)처럼 사용하면 되고,
만약 어떠한 field에 이미 접근 제어자가 작성되어 있어도 @FieldDefaults 어노테이션이 적절하게 바꿔준다.
private로만 사용해야 하는 field가 있다면, 해당 field에 @PackagePrivate라는 어노테이션을 붙여주면 된다.
모든 field에 final 키워드를 추가해주려면 makeFinal라는 옵션의 값에 true를 주면 되고(@FieldDefaults(makeFinal = true)),
만약 final로 만들면 안 되는 field가 있다면, 해당 field에 @NonFinal라는 어노테이션을 붙여주면 된다.
5. @Getter
글 상단부에서 언급했듯이, @Setter와 @Getter는 요즘 모르는 Spring 개발자는 거의 없으므로 패-쓰.
주의사항 및 단점
@Value 어노테이션은 @AllArgsConstructor을 포함하기 때문에 이전에 작성한 글과 동일한 주의사항 및 단점을 갖고 있다.
그 때문에 혹자는 @Value 대신, 아래처럼 사용하는 것을 권장한다.
@Getter
@ToString
public class Customer {
// private final을 직접 작성하여 field 생성
// 생성자 혹은 equals(), hashCode() 메소드가 필요하다면 직접 작성
}
끝!
'Study > Lombok' 카테고리의 다른 글
[Lombok] 공식 문서를 통해 알아보는 @NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor + 사용시 주의사항(단점) (0) | 2022.05.15 |
---|