Java record

hoyong.eom·2024년 10월 1일

자바

목록 보기
1/5
post-thumbnail

📒record

오늘은 레코드(record)에 대해서 공부한 내용을 포스팅하려고 한다.

record는 토이 프로젝트를 하면서 dto를 어떤걸로 만들면 좋을지 이야기를 하다가 알게 됐고, 회사에서도 서비스를 다시 만들때 사용하고 dto로 사용하고 있었다.

그래서 record에 대해서 정리를 해야겠다 라는 생각에 포스팅으로 정리해놓으려고 한다.


📌record란?

record에 대해서 구글링을 해보면 record의 목적은 아래와 같은 이유들 때문에 생성되었다고 한다.

  • boilerplate code로 인한 동일하고 지루한 프로세스 반복
  • 새 필드가 추가된 경우 자동으로 boilerplate code 업데이트 불가
  • boilerplate code(Getter, Setter, toString) 등으로 인해 데이터를 표현하기 위한 클래스의 의도가 불분명해짐

boilerplate code란?
컴퓨터프로그래밍에서 boilerplate code라고 부르는 것은 최소한의 변경으로 여러곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 말한다.

즉, 기존의 클래스에 Getter, Setter, toString과 같은 반복적으로 동일한 형태로 작성하던 코드들에 의해서 java 14부터 record가 탄생하게 되었다.

record로 생성했다는 의미는 클래스가 데이터 클래스임을 명시적으로 선언한것이라고 볼 수 있겠다.

정리하면 record로 DTO를 표현하기에 더할나위 없이 좋겠다!


📌record 기능

앞서 정리했던 내용으로 보면 record는 DTO로 표현하기에 매우 적합한 형태라고 볼 수 있겠다. (PS에서도 사용할 수 있으면 좋겠지만 대부분 Java11이라 불가능...)

report 특징

  • record는 필드 유형과 이름만 필요한 불변 데이터 클래스이며, 필드들은 private final로 선언된다.
  • equals, hashcode, tostring 메서드와 private, final field, public constructor는 Java 컴파일러에 의해서 생성된다.
  • 객체 지향에 맞게 데이터를 간결하게 표현하기 위한 방법을 제공하기 위한 의도
  • 불변 객체로 abstract로 선언할 수 없으며 암시적으로 final로 선언되고, 상속이 불가능하다
  • 다른 클래스를 상속받을 수 없지만 인터페이스 구현은 가능하다.
  • record 내부에 멤버변수를 선언할 수 없다. 그러나 static 변수는 생성이 가능하다.
  • static 메소드, 필드 선언 가능하다.

📌📌생성자

record를 생성면 필드에 선언된 argument가 있는 public constructor가 자동으로 생성된다.

class Main {
    public record User(String name, int age) {
    }
    
    public static void main(String[] args) {
        User user = new User("name", 20);
        System.out.println("############## public Constructor");
        System.out.println(user);
    }
}

실행 결과
############## public Constructor
User[name=name, age=20]

📌📌Getter

Getter 메서드도 자동으로 생성된다.

class Main {
    public record User(String name, int age) {
    }

    public static void main(String[] args) {

        User user = new User("name", 20);

        System.out.println("############## public Constructor");
        System.out.println(user);

        System.out.println("############## Getter");
        System.out.println("user.age() : " + user.age());
        System.out.println("user.name() : " + user.name());
    }
}

실행 결과
############## public Constructor
User[name=name, age=20]
############## Getter
user.age() : 20
user.name() : name

📌📌equals, hashcode, toString

equals, hashcode, toString 함수도 자동으로 생성합니다.

   public static void main(String[] args) {

        User user = new User("name", 20);
        User userCmp = new User("cmp", 21);

        System.out.println("############## public Constructor");
        System.out.println(user);

        System.out.println("############## Getter");
        System.out.println("user.age() : " + user.age());
        System.out.println("user.name() : " + user.name());

        System.out.println("############## equals");
        if (user.equals(userCmp)) {
            System.out.println("equal");
        } else {
            System.out.println("not equal");
        }

        System.out.println("############## toString");
        System.out.println("user.toString() : " + user.toString());
        System.out.println("userCmp.toString() : " + userCmp.toString());

        System.out.println("############## hashCode");
        System.out.println("user.hashCode() : " + user.hashCode());
        System.out.println("userCmp.hashCode() : " + userCmp.hashCode());
    }

실행 결과
############## public Constructor
User[name=name, age=20]
############## Getter
user.age() : 20
user.name() : name
############## equals
not equal
############## toString
user.toString() : User[name=name, age=20]
userCmp.toString() : User[name=cmp, age=21]
############## hashCode
user.hashCode() : 104584937
userCmp.hashCode() : 3057551

📌📌Compact Constructor(컴팩트 생성자)

컴팩트 생성자는 생성자 매개변수를 받는 부분이 사라진 형태의 생성자를 말한다.
컴팩트 생성자는 최대한 간단하게 유지해야하며 필드 validation 용도로 사용하는게 좋으며, 필드 초기화 로직은 마지막에 자동으로 호출된다.

class Main {
    public record User(String name, int age) {

        public User{
            System.out.println("Compact Constructor Called");
        }
    }

    public static void main(String[] args) {

        User user = new User("name", 20);
        User userCmp = new User("cmp", 21);
    }
}

실행 결과
Compact Constructor Called
Compact Constructor Called
user : User[name=name, age=20]
userCmp : User[name=cmp, age=21]

실행 결과를 보면 컴팩트 생성자가 호출되고, 필드도 호출된걸 확인할 수 있다.

컴팩트 생성자와 생성된 생성자와 일치하는 인수 목록을 가진 생성자를 선언하면 컴파일 오류가 발생한다.

    public record User(String name, Integer age) {

        public User{
            Objects.requireNonNull(name);
            Objects.requireNonNull(age);
        }

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

    }

참고

https://docs.oracle.com/en/java/javase/14/language/records.html
https://velog.io/@pp8817/record
https://charlezz.medium.com/%EB%B3%B4%EC%9D%BC%EB%9F%AC%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%9E%80-boilerplate-code-83009a8d3297
https://colevelup.tistory.com/28
https://www.baeldung.com/java-record-keyword

0개의 댓글