Java Record

U_Uracil·2023년 12월 19일
0

Java

목록 보기
1/2

Record

  • Java 14에서 도입, 16에서 정식으로 채택되었다.
  • 특수한 유형의 클래스이다.

Record 사용 예시


불변 데이터 객체를 기존 방식(class)으로 구현

public class SampleRecord {
    private final String name;
    private final int age;
    private final String address;

    public Reee(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Reee reee = (Reee) o;
        return age == reee.age && Objects.equals(name, reee.name) && Objects.equals(address, reee.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, address);
    }

    @Override
    public String toString() {
        return "Reee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
  1. 모든 field에 final 키워드 사용
  2. 모든 field를 포함한 생성자 작성
  3. 접근자 메서드(getter) 작성
  4. equals()와 hashCode() 오버라이딩
  5. 상속을 방지하려면 class에 final 키워드 사용
  6. toString 오버라이딩

불변 데이터 객체를 Record로 구현

public record SampleRecord(
        String name,
        int age,
        String address
) {}
  • Record는 이름(SampleRecord), 헤더(String name, int age, String address), 바디({}) 로 구성된다.
  • 위의 코드와 비교했을 때 코드가 매우 간결해진다.

Record의 기능


1. 필드 캡슐화

1

  • Record의 헤더에 들어 있는 field를 private final 형태로 갖고 있다.

2. 메서드 자동 생성

2

3

4

5

6

  • 생성자, 접근자, equals(), hashCode(), toString() 메서드를 컴파일 타임에 컴파일러가 자동으로 생성한다.
  • 컴파일러는 헤더를 통해 내부 필드를 추론한다.
  • 접근자는 getFieldName() 형태가 아니라 fieldName()의 형태이다.

Record의 활용

  • Record는 모든 필드를 매개변수로 가지는 생성자를 기본적으로 제공한다. 기본 제공 생성자가 하지 못하는 데이터 검증이나, 일부의 값만 전달받는 생성자를 만드는 것도 가능하다. 이러한 생성자를 컴팩트 생성자라고 한다.

    • 나이를 검증하는 로직이 들어간 컴팩트 생성자
      public record SampleRecord(
              String name,
              int age,
              String address
      ) {
          public SampleRecord {
              if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
          }
      }
    • 주소를 입력받지 않는 컴팩트 생성자
      public record SampleRecord(
              String name,
              int age,
              String address
      ) {
          public SampleRecord(String name, int age) {
              this(name, age, "Unknown Address");
          }
      }
  • 레코드는 static field와 method를 가질 수 있다.

    public record SampleRecord(
            String name,
            int age,
            String address
    ) {
        // static field
        public static String UNKNOWN_ADDRESS = "Unknown Address";
    
        public SampleRecord(String name, int age) {
            this(name, age, UNKNOWN_ADDRESS);
        }
        
        // static method
        public static SampleRecord unnamed(int age, String address) {
            return new SampleRecord("Unnamed", age, address);
        }
    }
    SampleRecord.unnamed(20, "Seoul");
    String unknownAddress = SampleRecord.UNKNOWN_ADDRESS;

Record의 제한 사항

  • Record는 다른 클래스를 상속받을 수 없다. (인터페이스의 implements는 가능)
  • private final field 외에 인스턴스 필드를 선언할 수 없다.
  • 선언되는 다른 모든 field는 static이어야 한다.
    • 위의 제한 사항들을 통해 상태 설명만으로 표현을 정의할 수 있도록 보장해준다.
  • Record는 final이며, abstract일 수 없다.
    • 이 제한 사항을 통해 나중에 다른 클래스 or 레코드에 의해 변경될 수 없음을 보장한다.

Record 언제 사용할까?

  • DTO
  • 불변성을 보장해야 하는 객체
  • 단순 값 유형
  • API 응답
  • Config 세팅

References
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Record.html
https://medium.com/javarevisited/java-records-when-why-to-use-them-ebd48de637b6
https://colevelup.tistory.com/28
https://www.baeldung.com/java-record-keyword
https://scshim.tistory.com/372

profile
기억은 유한, 기록은 무한

0개의 댓글