Lombok 생성자 어노테이션 @NoArgsConstructor 과 @AllArgsConstructor
@NoArgsConstructor
@NoArgsConstructor 는 매개변수가 없는 기본 생성자(default constructor)를 생성한다. 필드를 초기화하지 않고 객체를 생성할 때 유용하다. 예를 들어, Spring과 같은 프레임워크에서 빈(Bean)으로 객체를 등록할 때 자주 사용된다.
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Example {
private String name;
private int age;
}
위 코드는 Example 클래스에 매개변수가 없는 기본 생성자를 추가한다. new Example() 로 인스턴스를 생성할 수 있다.
@AllArgsConstructor
@AllArgsConstructor 는 모든 필드를 초기화 하는 생성자를 생성한다. 클래스에 있는 모든 필드를 매개변수로 받는 생성자를 자동으로 추가하여 초기화에 유용하다.
import lombok.AllArgsConstructor;
@AllArgsContructor
public class Example {
private String name;
private int age;
}
위 코드에서는 name 과 age 필드를 초기화하는 생성자가 생성된다. new Example("John", 25) 와 같이 객체를 생성할 수 있다.
두 어노테이션을 함께 사용하는 이유
- 프레임워크와의 호환성:
Spring 같은 프레임워크에서는 기본 생성자가 필요하다. @NoArgsConstructor 를 사용해서 기본 생성자를 제공하면, 빈(bean)으로 등록할 때 편리하다 - 테스트와 객체 초기화의 유연성:
기본 생성자로 생성한 객체에 setter 메서드를 이용해 필드를 설정할 수 있고, @AllArgsConstructor 로 모든 필드를 초기화하는 생성자를 제공하여 한 번에 객체를 완성할 수도 있다. - 불변성 유지:
@AllArgsConstructor 와 함께 @NoArgsConstructor 를 사용하면서도, final 필드를 활용하여 필요한 경우에 불변 객체를 만들 수 있다. 이때 @NoArgsConstructor(force = true) 옵션을 주면 final 필드도 기본값으로 초기화 된다
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class Example {
private String name;
private int age;
public static Example of(String name, int age) {
return new Example(name, age);
}
}
@NoArgsConstructor 와 @AllArgsConstructor 를 함께 사용하면:
- 기본 생성자:
Example ex = new Example(); 로 객체를 생성하고, 이후 setter 로 필드 값을 설정할 수 있다. - 모든 필드 초기화 생성자:
new Example("John", 30); 으로 한 번에 모든 필드를 설정하여 객체를 생성할 수 있다. - 팩토리 메서드:
Example.of("John", 30); 을 통해 호출을 캡슐화하여 더 직관적인 객체 생성을 할 수 있다.
@NoArgsConstructor 와 @AllArgsConstructor 를 각각 사용하면:
1. @NoArgsConstructor 만 사용하는 경우
- 이점: 기본 생성자만 생성되므로, 객체를 생성한 후 setter 를 통해 필요한 필드를 설정할 수 있다.
- 제약사항: 객체를 생성한 후 별도로 필드 값을 설정해야 하므로, 필드가 많은 경우 코드가 길어질 수 있다. 그리고 final 필드는 기본 생성자로 초기화할 수 없으므로 @NoArgsConstructor(force = true) 옵션이 필요할 수 있다.
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Example {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
이 경우에는 필드를 하나씩 설정해야 한다.
2. @AllArgsConstructor 만 사용하는 경우
- 이점: 모든 필드를 초기화하는 생성자가 생성되므로, 객체 생성 시 한 번에 모든 필드를 설정할 수 있어 초기화가 간편하다.
- 제약사항: Spring 같은 프레임워크에서 기본 생성자가 필요할 때 문제가 될 수 있다. 또한, 모든 필드를 초기화해야만 객체를 생성할 수 있어 일부 필드를 생략한 객체 생성을 원할 경우 제한이 있다.
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class Example {
private String name;
private int age;
}
이 경우에는 new Example("John", 30); 으로 모든 필드를 초기화할 수 있지만, 기본 생성자가 없으므로 new Example(); 은 사용할 수 없다.
기본 생성자가 없을 때 발생할 수 있는 문제들
Java 컴파일러는 별도의 생성자를 정의하지 않은 경우에 자동으로 기본 생성자(파라미터가 없는 생성자)를 추가해준다.
하지만 @AllArgsConstructor 를 붙이면 모든 필드를 초기화하는 생성자가 생성되기 때문에 기본 생성자는 자동으로 생성되지 않는다.
- 프레임 워크 사용 시 문제:
- Spring이나 JPA와 같은 프레임워크는 종종 기본 생성자를 통해 객체를 생성한다. 이 프레임워크들은 리플렉션(reflection)을 통해 빈(bean) 또는 엔티티(entity) 객체를 생성할 때 기본 생성자를 필요로 한다.
- 예를 들어, JPA 엔티티 클래스에 기본 생성자가 없으면 @Entity클래스의 객체를 생성할때 NoSuchMethodException 이 발생할 수 있다. 이는 JPA가 파라미터 없는 기본 생성자를 사용하여 엔티티를 만들기 때문이다. - JSON 직렬화/역직렬화에서 문제:
- Jackson이나 Gson같은 JSON 직렬화/역직렬화 라이브러리도 기본 생성자를 통해 객체를 생성하는 경우가 많다. 기본 생성자가 없으면 JSON 데이터를 객체로 역직렬화할 때 에러가 발생할 수 있다.
- 특히 JSON 역직렬화가 필요한 Spring MVC의 @RequestBody와 같은 기능을 사용할 때 기본 생성자가 없으면 객체를 생성하지 못해 에러가 발생한다. - 객체 생성의 유연성 부족:
- 기본 생성자가 없으면 객체를 생성할 때 반드시 모든 필드를 초기화해야하는 제약이 생긴다. 어떤 필드는 나중에 설정하고 싶을 수 있는데, 기본 생성자가 없으면 이를 유연하게 처리할 수 없다.
- 기본 생성자가 있는 경우 객체를 생성한 후 setter 메서드로 필요한 필드만 설정할 수 있지만, 기본 생성자가 없으면 생성 시 모든 필드에 값을 전달해야 한다.
=> @NoArgsConstructor 는 혼자 써도 문제가 없지만, @AllArgsConstructor 는 기본 생성자를 필요로 하는 상황이 많기 때문에 일반적으로 @NoArgsConstructor 과 함께 사용하는 것이 좋다.
어노테이션을 붙이지 않아도 되는 경우
- 단순 객체 생성 시: 예를 들어, 특정 객체를 생성할 때 기본 생성자로 충분하고, 모든 필드를 초기화하는 생성자가 필요하지 않다면 어노테이션이 없어도 문제가 없다.
- Getter, Setter 사용만 필요한 경우: 필드를 나중에 setter 로만 설정할 계획이라면 굳이 모든 필드를 초기화하는 생성자를 만들 필요는 없다.
'Java > 기본' 카테고리의 다른 글
[Java] 컴파일 오류? 런타임 오류? (1) | 2024.11.14 |
---|---|
[Java] 순환참조 (1) | 2024.11.14 |
[Java] 트랜잭션 (0) | 2024.11.11 |
[Java] CompletableFuture (0) | 2024.11.08 |
[Java] Future (0) | 2024.11.08 |