2023. 6. 12. 03:03ㆍJAVA
레코드란?
- 불변(immutable) 객체를 쉽게 생성할 수 있도록 하는 유형의 클래스입니다.
- JDK14에서 preview로 등장하여 JDK16에서 정식 스펙으로 포함되었습니다.
저는 JDK 17 LTS 버전으로 프로젝트를 진행하며 레코드 클래스의 장점을 맛봤습니다.
Before
학생(Student) 클래스에 이름과 나이 필드가 있다고 가정하겠습니다.
Record를 사용하기 전에, Student를 불변 객체를 생성하기 위해서는 다음과 같이 코드를 작성해야 합니다.
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
- 모든 필드에 final 선언
- 필드 값을 모두 포함한 생성자
- 접근자 메서드(getter)
- 클래스의 상속을 제한하려면 클래스 레벨에도 final 선언
After
다음은 동일한 조건의 Student 객체를 record를 이용해 구현한 코드입니다.
public record Student(String name, int age) {
}
record를 사용하면 아래의 내용들을 직접 구현하지 않아도 자동으로 생성됩니다.
- 필드 캡슐화
- 생성자 메서드
- getters 메서드
- equals 메서드
- hashcode 메서드
- toString 메서드
이것이 가능한 이유는, 컴파일 타임에 컴파일러가 코드를 추가해주기 때문입니다.
아래 더보기에서 바이트 코드를 확인하실 수 있습니다.
바이트 코드 확인하기
IntelliJ의 Bytecode Decompiler 기능을 이용하면 컴파일 된 User.class의 바이트코드를 손쉽게 확인할 수 있습니다.
1. build > classes > java > main 하위에서 User.class 파일을 클릭합니다.
2. 상단의 View에서 Show ByteCode를 클릭합니다.
3. 바이트코드 확인
- 가장 먼저 class가 final로 선언되어 있는 것을 확인할 수 있습니다.
- 또한 name과 age 필드도 private final로 선언되어 있습니다.
- <init>(Ljava/lang/String;I)V 는 JVM이 생성자로 인식하는 서명입니다.
괄호 속 String; I는 해당 생성자가 String과 int 두 개의 매개변수를 받는 것임을 표시하고 있습니다. - 커서를 더 내리다보면 toString(), hashCode(), equals() 메소드도 확인할 수 있습니다.
컴파일러가 이 메소드들을 컴파일 타임에 추가해준 덕에, 직접 작성하지 않은 메소드들을 바이트 코드에서 확인할 수 있었습니다.
기존 Class와 차이점이 있다면 getter를 사용할 때, getFieldName()이 아니라 fieldName()을 사용한다는 점입니다.
Student student = new Student("kim", 20);
System.out.println(student.getName()); //일반 Class
System.out.println(student.name()); //Record Class
기본적으로 Record 클래스가 제공해주는 메소드들은 재정의가 가능합니다.
다음은 생성자를 재정의해서 사용하는 예시입니다.
public record Student(String name, int age) {
public Student {
if(age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
}
}
Q. 레코드(record)를 JPA의 Entity 클래스로 사용할 수 없을까요?
레코드는 바이트코드로 본 것처럼 final 클래스(상속불가)이고, abstract로 선언할 수 없습니다.
따라서 레코드를 Entity 클래스에 사용할 수 없는데요, 그 이유는 JPA의 지연로딩에 있습니다.
지연 로딩 방식을 사용할 때, JPA는 엔티티 객체의 프록시 객체를 생성합니다. 프록시 객체는 원본 객체를 상속하여 생성된 확장 클래스입니다. 하지만 레코드는 상속이 불가능하므로 엔티티로 사용할 수 없습니다.
참고
https://blog.jetbrains.com/wp-content/uploads/2020/03/idea-decompiler-bytecode.png
'JAVA' 카테고리의 다른 글
스트림(Stream) 소개 (0) | 2022.12.25 |
---|---|
JIT compiler (2) | 2022.12.11 |
Java - Calculator 과제 회고 (0) | 2022.10.30 |
Java 숫자야구 (0) | 2022.10.21 |
Collection과 Iterator (0) | 2022.10.20 |