생성자 자동 생성자 올바르게 사용하기
- 우선
Lombok
에서 제공하는 어노테이션 3개를 떠올릴 수 있다.
@NoArgsConstructor
- 매개변수가 없는 기본 생성자를 자동으로 생성
JPA
에서는 프록시를 생성을 위해서 기본 생성자를 반드시 하나를 생성해야한다.
@NoArgsConstructor
public class Example {
private String field;
}
↓
public class Example {
private String field;
public Example() {
}
}
@AllArgsConstructor
- 모든 필드를 매개변수로 받는 생성자를 자동으로 생성
- 매우 편리하게 생성자를 만들어주지만, 별 생각없이 작성한 코드가 치명적인 버그를 만들어낼 수도 있다.
@AllArgsConstructor
public class Example {
private String field;
}
↓
public class Example {
private String field;
public Example(String field) {
this.field = field;
}
}
@RequiredArgsConstructor
- 필드 중 초기값이 할당되지 않은
final
필드, 그리고 @NonNull
어노테이션으로 표시된 필드를 매개변수로 받는 생성자를 자동으로 생성
@RequiredArgsConstructor
public class Example {
private final String field1;
@NonNull
private String field2;
}
↓
public class Example {
private final String field1;
private String field2;
public Example(String field1, String field2) {
if (field2 == null) {
throw new NullPointerException("field2 is marked non-null but is null");
}
this.field1 = field1;
this.field2 = field2;
}
}
결론
- 물론 편하게 위 생성자를 사용해서 생성자를 만드는것도 좋지만, 사소한 객체 생성부터 고민해보는 것이 클린 코드, 유지 보수를 고려한 좋은 코드를 만들 수 있는 습관이 된다고 한다.
- 최대한
@RequiredArgsConstructor
, @AllArgsConstructor
사용을 지양하며 @NoArgsConstructor
에 생성자의 접근레벨을 PROTECTED
로 해준뒤 생성자를 생성할경우 @Builder
를 붙여주는 방향으로 해야겠다.
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReviewImage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
@ManyToOne
private Review review;
@NotNull
private String imageUrl;
}
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CommentImage {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "comment_id")
private Comment comment;
@NotNull
private String imageUrl;
@Builder
public CommentImage(Comment comment, String imageUrl) {
this.comment = comment;
this.imageUrl = imageUrl;
}
}