본문 바로가기
JAVA

Records

by oncerun 2023. 7. 11.
반응형

JEP 395에는 레코드를 다음과 같이 요약했습니다.

 

Enhance the Java programming language with records, which are classes that act as transparent carriers for immutable data. Records can be thought of as nominal tuples.

 

자바 14, 15 preview에서 2021년 3월 16일 JDK 16에 General Availabilty에 도달하면서

 

Java 레코드는 공식적으로 언어의 일부가 된  Records는 불변 데이터 객체를 매우 쉽게 정의할 수 있는 새로운 형태의 클래스이며 데이터를 저장하고, 접근하기 위한 필드와 해당 필드에 대한 접근자 메서드를 자동으로 생성해 줍니다.

 

21년 9월 19일 JDK 17 (LTS) 릴리스로써 이제 프로덕션 코드에 Java Records를 사용할 수 있습니다.

 

타 언어에서는 데이터 지향 클래스를 모델링하기 위한 간결한 구문 형식을 사용해 왔습니다.

Scala의 case classes, Kotlin의 data class, C#의 record class가 대표적입니다. 

 

 

레코드는 record 키워드를 사용하여 정의됩니다.

 

public record Person(String name, int age) {
}

 

위 예시는 name, age는 레코드의 필드입니다. 이는 불변하기 때문에 생성된 이후에는 필드 값을 변경할 수 없습니다. 

 

필드를 읽기 위한 getter 메서드가 생성되는데, String getName(), int getAge() 메서드가 생성됩니다. 

 

또한 자바 레코드는 equals(), hashCode(), toString() 등의 메서드를 자동으로 생성합니다. 

 

이는 객체의 동등성 비교, 해시 코드 생성 및 문자열 표현을 위한 표준 기능을 생성하여 제공해 줍니다. 

 

간결성과 가독성, 불변성을 Java 클래스로 한 번 정의하고, 이후 records로 비교해보려고 합니다.

 

우선 자바 클래스로 다음과 같이 작성합니다.

 

  public class PersonJava {

        private final String name;
        private final List<String> friends;

        public PersonJava(String name, List<String> friends) {
            this.name = name;
            this.friends = friends;
        }

        public String getName() {
            return name;
        }

        public List<String> getFriends() {
            return friends;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            PersonJava that = (PersonJava) o;
            return Objects.equals(name, that.name) && Objects.equals(friends, that.friends);
        }

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

        @Override
        public String toString() {
            return "PersonJava{" +
                    "name='" + name + '\'' +
                    ", friends=" + friends +
                    '}';
        }
    }

 

이를 record를 사용하도록 변경해 보겠습니다.

   public record Person (String name, List<String> friends) {
    }

 

 

Goal

 

레코드의 목적은 다음과 같습니다.

 

1. 단순한 값의 집합을 표현하는 객체 지향 구조를 고안하는 것입니다.

 

2. 개발자가  확장 가능한 동작이 아닌, 불변 데이터 모델링에 집중할 수 있도록 지원합니다.

 

3. 편의성 및 생산성을 위해 equals, getter와 같은 데이터 기반의 메서드를 자동으로 구현합니다.

 

4. Java 레코드가 기존 Java 코드와 호환되도록 설계되었으며, 변수의 유형이 값이 아닌 이름에 의해 결정됩니다.

 

5. 마이그레션 호환성이 있어, 코드를 변경하지 않고도 기존 Java 코드에서 record를 사용할 수 있습니다.

 

 

Non-Goal

 

war on boilerplate

 

자바 레코드는 data carrier classes를 더 쉽게 선언할 수 있도록 설계되었지만 모든 보일러플레이트 코드를 제거하기 위한 것은 아닙니다.  (실제 record에는 여전히 생성자가 존재하며, 초기화를 해야 합니다.)

 

 

JavaBeans Spec

 

JavaBeans는 재사용 가능한 Java 구성 요소를 생성하기 위한 명세입니다.

일반적으로 JavaBeans의 구성 요소는 가변적이며, 특정한 명명 규칙을 사용하여 속성을 사용합니다. 

 

JavaBeans 명명 규칙은 속성 이름이 get으로 시작하고 set으로 끝나는 것을 요구합니다. 예를 들어, "name" 속성은 "getName()" 및 "setName()" 메서드를 사용하여 액세스 할 수 있습니다.

 

Java 레코드는 JavaBeans 명명 규칙을 따르지 않습니다. Java 레코드는 불변 클래스이며, 속성 이름이 get으로 시작하거나 set으로 끝나는 것을 허용하지 않습니다. 

 

 

POJO

 

record는 속성이나 어노테이션 기반 코드 생성을 사용하지 않습니다. 컴파일러에 의해 자동으로 생성됩니다.

 

 

 

정리

 

 

내가 생각하기에는 레코드는 다음과 같다.

 

레코드는 타입의 유형을 데이터임을 표현한다.

 

이를 위해 상속을 막아 숨겨진 상태를 추가할 수 없고 접근자의 이름을 변경할 수 없으며 반환 유형을 변경할 수도 없고, 값을 변경해서도 안된다.  또 레코드는 구성 요소의 값의 재할당도 허용하지 않는다. 

 

만약 이러한 작업이 필요하다면 이는 레코드가 필요한 것이 아니라 일반적인 클래스를 만들어야 함을 의미한다. 

 

불변의 데이터의 집합을 엄격하게 타입으로 묶어 표현하고 투명하게 접근 가능한 것.

 

이를 보장하기 위한 제약조건들을 지키며 사용할 수 있을 때 필요한 것은 Record이다. 

 

 

 

 

https://www.baeldung.com/java-immutable-object

https://openjdk.org/jeps/395

 

 

반응형

'JAVA' 카테고리의 다른 글

ZGC (HotSpot)  (0) 2023.07.11
Java Duration and Period Class  (0) 2023.02.23
Code Cache  (1) 2023.02.18
Java 11 HttpClient Class  (0) 2022.12.13
S3 다중 업로드를 병렬로 처리 시 발생할 수 있는 문제..(CountDownLatch)  (0) 2022.12.03

댓글