BackEnd/Java
Java 16. Record Class
hanseom
2024. 12. 8. 09:00
반응형
Record Class
Java 14 preview, Java 16 정식으로 출시된 기능으로 데이터 전달을 위해 등장한 클래스입니다.
다음은 데이터 전달을 위한 DTO 클래스입니다.
import java.time.LocalDate;
import java.util.Objects;
public final class FruitDto {
private final String name; // 과일 이름
private final int price; // 과일 가격
private final LocalDate date; // 과일 입고 일자
public FruitDto(String name, int price, LocalDate date) {
this.name = name;
this.price = price;
this.date = date;
}
public String name() {
return name;
}
public int price() {
return price;
}
public LocalDate date() {
return date;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FruitDto fruitDto = (FruitDto) o;
return price == fruitDto.price && Objects.equals(name, fruitDto.name) && Objects.equals(date, fruitDto.date);
}
@Override
public int hashCode() {
return Objects.hash(name, price, date);
}
@Override
public String toString() {
return "FruitDto[" +
"name='" + name + '\'' +
", price=" + price +
", date=" + date +
']';
}
}
- class에 final이 선언되어 있어서 다른 클래스가 상속 받지 못합니다.
- private final 필드만 선언되어 있습니다.
- 모든 private final 필드에 대해 생성자가 존재합니다.
- 클래스가 갖고 있는 모든 필드에 접근할 수 있는 메소드가 있고, 메소드의 이름은 필드의 이름과 동일합니다.
- equals() / hashCode() / toString()이 존재합니다.
개발을 하다보면 이러한 데이터 전달 객체 (DTO)를 꽤 많이 만들게 됩니다. 다음은 위의 FruitDto 클래스를 Record 클래스로 구현한 코드입니다.
public record FruitDtoV2(
String name, // 컴포넌트(Component)
int price,
LocalDate date
) {
}
- 일반적인 클래스와 다르게 ()로 시작합니다.
- () 안에는 Record 클래스가 갖고 있을 필드들을 선언합니다.
- FruitDtoV2 Record 클래스는 FruitDto 클래스와 완전히 동일합니다.
- 다른 클래스가 상속 받을 수 없습니다.
- 컴포넌트에 대한 private final 필드가 자동으로 생성됩니다.
- name, price, date를 받아 필드에 값을 할당하는 생성자도 자동으로 생성됩니다.
- 필드에 접근할 수 있는 name(), price(), date() getter가 자동으로 생성됩니다.
- equals() / hashCode() / toString() 자동으로 생성됩니다.
Record Class 특징
- 다른 클래스를 상속 받을 수 없습니다.
- 인터페이스는 구현이 가능합니다.
- static 필드, 함수, 인스턴스 함수 등을 만들 수 있습니다. 단, 인스턴스 필드는 만들 수 없습니다.
- 자동 생성되는 메소드들을 직접 재정의 할 수 있습니다.
- 값을 검증하려면 일반적인 생성자 대신 compact constructor를 사용할 수 있습니다.
public record FruitDtoV2(
String name,
int price,
LocalDate date
) {
private static final double DISCOUNT_RATE = 0.3;
public int getDiscountPrice() {
return (int) (price * (1.0 - DISCOUNT_RATE));
}
// compact constructor
public FruitDtoV2 {
System.out.println("생성자 호출!");
// 값 검증
if (price < 0) {
// price = 0; // this를 사용할 수 없습니다. 값을 변경하려면 일반적인 필드를 사용합니다.
throw new IllegalArgumentException("과일의 가격은 양수입니다!");
}
}
public String name() {
return "[재정의] " + this.name;
}
}
compact constructor: 매개변수를 전혀 받지 않아 문법적으로 간결합니다. 단, 필드에 값을 할당할 시 this를 사용할 수 없습니다.
Record Class와 스프링 부트
- Jackson 2.12.0 이상(Spring Boot 2.5.x 이상)에서 Record 클래스 사용이 가능합니다.
- HTTP 쿼리 파라미터와 바디 모두 잘 적용됩니다.
- Record 클래스를 사용하면 lombok의 어노테이션 없이 데이터 전달 클래스를 생성할 수 있습니다.
반응형