@AllArgsConstructor
, @RequiredArgsConstructor
(사용 금지 권장)
테스트 클래스 정의
@AllArgsConstructor
public static class PriceInfo {
private int price;
private int discountPrice;
}
// 정상가격 3,000원, 할인가격 1,000원
PriceInfo priceInfo = new PriceInfo(3000, 1000);
필드의 순서가 변경
@AllArgsConstructor
public static class PriceInfo {
private int discountPrice;
private int price;
}
// 할인가격 3,000원, 정상가격 1,000원
PriceInfo priceInfo = new PriceInfo(3000, 1000);
이러한 경우에는 IDE가 제공하는 리팩토링이 작동하지 않을 뿐더러 Lombok 또한 개발자들이 인식하지 못하는 사이에 생성자의 파라미터 순서를 필드 선언 순서에 맞춰 생성자의 매개변수 순서를 변경해버린다. 또한 두 필드는 동일한 데이터 타입이므로 매개변수 순서가 변경되어도 어떠한 오류도 발생하지 않는다.
해결방안
@Builder
사용
public static class PriceInfo {
private int price;
private int discountPrice;
@Builder
private PriceInfo(int price, int discountPrice) {
this.price = price;
this.discountPrice = discountPrice;
}
}
// 필드 순서를 변경해도 문제 없음
PriceInfo priceInfo = PriceInfo.builder()
.discountPrice(1000)
.price(3000)
.build();
@EqualsAndHashCode
(사용 지양)
@EqualsAndHashCode
는 상당히 고품질의 equals
, hashCode
메소드를 만들어준다. 잘 사용하면 좋지만 남발하면 심각한 문제가 생긴다.
특히 문제가 되는 점은 바로 Mutable(변경가능한) 객체에 아무런 파라미터 없이 그냥 사용하는 @EqualsAndHashCode
어노테이션이다.
@EqualsAndHashCode
public static class Order {
privateLong orderId;
private long orderPrice;
private long cancelPrice;
public Order(Long orderId, long orderPrice, long cancelPrice) {
this.orderId = orderId;
this.orderPrice = orderPrice;
this.cancelPrice = cancelPrice;
}
}
Order order = new Order(1000L, 19800L, 0L);
Set<Order> orders = new HashSet<>();
orders.add(order);// Set에 객체 추가
System.out.println("변경전 : " + orders.contains(order));// true
order.setCancelPrice(5000L);// cancelPrice 값 변경System.out.println("변경후 : " + orders.contains(order));// false
동일한 객체임에도 Set 에 저장한 뒤에 필드 값을 변경하면 hashCode가 변경되면서 찾을 수 없게 되어버린다. 그러므로 최소한 꼭 필요하고 일반적으로 변하지 않는 필드에 대해서만 만들도록 노력해야 한다.
@Data
(사용 금지 권장)
@ToString
, @EqualsAndHashCode
, @Getter
, @Setter
, @RequiredArgsConstructor
를 모두 포함한 어노테이션이다
권장 사용법
필요한 어노테이션만 선언하여 사용 (@Getter / @ToString 등등...)
@Value
(사용 지양)
<aside>
💡 org.springframework.beans.factory.annotation.Value
와 다름
</aside>
Immutable 클래스를 만들어주는 조합 어노테이션이지만 이 또한 @EqualsAndHashCode,
@AllArgsConstructor
를 포함한다. @EqualsAndHashCode
는 불변 클래스라 큰 문제가 안되지만 @AllArgsConstructor
가 문제가 된다. 그러므로 아래와 같이 사용하자
@Getter
@ToString
public class Order {
// private final 로 여러 필드 생성
// 생성자와 필요한 경우에만 equals, hashCode 직접 작성
}
@Builder
를 생성자나 static 객체 생성 메소드에 사용 권장
@Builder
는 기본적으로 @AllArgsConstructor
를 내포하고 있으며 이걸로는 크게 문제가 안생기나 생성자를 private으로 만들기 때문에 외부에서 생성자를 호출할일은 쉽게 생기진 않는다. 그러나 해당 클래스의 다른 메소드에서 이렇게 자동으로 생성된 생성자를 사용할 때 문제를 발생시킬 수 있다.
public static class User{
private String pwd;
private String id;
@Builder
public User(String pwd, String id){
this.pwd = pwd;
this.id = id;
}
}
User user = User.builder()
.pwd("userPwd")
.id("userId")
.build();
@Slf4j
@Slf4j
는 Logger와 같이 field 변수로 만들 필요가 없어 static method에서도 호출이 가능하다.
@Slf4j
사용
@Slf4j
public class User{
public void logExample() {
log.info("logging!!");
}
}
LoggerFactory
사용
public class User{
Logger log = LoggerFactory.getLogger(getClass());
public void logExample() {
log.info("logging!!");
}
}
static이 아닌 필드로 만들고자 하거나 Logger 객체 이름을 변경하고자 한다면 lombok.config
를 사용하면 된다.
lombok.config
lombok.config를 통하여 애노테이션 사용금지 및 각종 설정
config.stopBubbling = true
lombok.data.flagUsage=error
lombok.value.flagUsage=error
lombok.val.flagUsage=error
lombok.var.flagUsage=error
lombok.nonNull.flagUsage=error
lombok.allArgsConstructor.flagUsage=error
lombok.requiredArgsConstructor.flagUsage=error
lombok.cleanup.flagUsage=error
lombok.sneakyThrows.flagUsage=error
lombok.synchronized.flagUsage=error
# experimental 전체 금지
lombok.experimental.flagUsage=error
# 로거 객체 이름을 logger로 변경. 원래는 log
lombok.log.fieldName=logger
# 로거를 static이 아닌 필드로 생성
lombok.log.fieldIsStatic=false
https://bkjeon1614.tistory.com/657 https://kwonnam.pe.kr/wiki/java/lombok/pitfall#log https://ksshlee.github.io/spring/java/lombok/#slf4j