상황:
record 의 static factory method 만들었다.
개인적인 기호는 new 보다 정적 팩토리 메소드를 사용하는 것을 선호한다.
따라서 타 클래스에서 new 를 통한 생성자를 직접 호출하는 대신, 정적 팩토리 메소드를 사용하도록 제한을 두기 위해 "생성자를 private" 으로 변경하고자 했다.
이미 정적 팩토리 메소드 내부에서는, 모든 불변 필드를 초기화하는 역할의 기본 생성자(이하 '주생성자' 라고 칭하겠음) 를 호출하는 방식을 취하도록 했다.
record 타입에서는 컴파일러가 자동으로 public 주생성자를 만들어주기 때문에, 이를 명시적으로 다시 정의해서 private 으로 해주려고 했다.
그런데 컴파일 에러가 발생했다
- 좀 더 구체적인 상황을 적자면 -> 해당 레코드 타입은 public record 이다 . ( 사실 이 상황이 안되는 이유에 대한 힌트이기도 함 )
아 먼가.. record 타입에 대한 문법의 이해가 부족해서 생긴 이슈 같다는 감이 왔드아..!!!!
record 의 생성자들
먼저 record 타입에서 "생성자"들을 지칭하는 다양한 용어들을 살펴보자..
문서를 보면 "compact constructor" 와 "canonical constructor" 라는 것이 등장하는데 여기서 "canonical constructor" 가 우리가 흔히들(???) 말하는.., 그리고 엘레강트 오브젝트에서는"주 생성자" 라고 부르는 것이다.
즉, 모든 불변 인스턴스 필드들을 초기화해주는 생성자에 해당한다.
그렇다면 compact constructor 는 또 무엇일까?
이름만 보면 생성자 같지만, 얘는 실제로는 생성자가 아니다..! 일단 이번 주제에서는 벗어나는 내용이라 패쓰~~~ 하겠다 ( 그리고 나중에 공부하겠다)
public record Product(String name, int quantity) {
// Non-canonical record constructor must delegate to another constructor
public Product(Product product) {
this(product.name(), product.quantity());
}
// Canonical record constructor
public Product(String name, int quantity) {
this.name = name;
this.quantity = quantity;
}
// Compact constructor
public Product {
name = "NONE";
quantity = UNKNOWN_QUANTITY;
}
// Not Allowed form of constructor
/*
public Product() {
}
*/
}
record 타입에서는, 기본적으로 canonical constructor 를 제공해준다. record 역시 "클래스" 이기 때문에, 여러 생성자를 정의, 즉 생성자 오버로딩이 가능하다. 하지만 이 때, "무조건 canonical constructor" 를 호출해야만 하다는 차이점이 존재한다. 그렇지 않으면 컴파일 에러가 발생한다
왜 그러한지 생각해보면, record 는 Java 에서 "불변 객체" 를 정의하기 쉽게 해주는 편리한 문법이다. 내부 모든 필드는 final 필드이고, 이들은 생성시 초기화 되는게 필요하다. record 목적 자체가 "불변 객체를 정의" 하는 것에 있기 때문에, 모든 생성자에서 "모든 불변 필드를 초기화 할 수 있도록 함을 보장" 하기 위함이 아닐까 추측해 보았다.
원인은 record 타입 문법과 관련이 있다
Java 17 부터는 record type 의 canonical constructor 에 대해 “ record 타입 클래스에 부여한 접근 제한 레벨" 보다 “ 더 강력한 레벨의 접근 제한" 을 하려고 할 경우, 컴파일 에러가 발생하도록 하였다. !!!
이것이 원인이었다.
현재 나의 record 타입 클래스는 public 클래스인데 , 이 접근제한 보다 강력한 제한 레벨인 private 을 가진 생성자로 만드려고 하기 때문에 컴파일 에러가 발생하는 것이었다.
해결 아닌 해결방법 고민..
따라서 new 를 사용한 생성에 제한을 두고 , 정적 팩토리 메소드만을 사용하게 하고 싶은 경우라면
현재로서는 “일반 클래스" 를 사용하여 불변 클래스를 따로 만드는 것이 필요할 것 같다.
현재는 정적팩토리 메소드를 사용한 이유가, 그저 가독성을 위함이었기 때문에 모든 정적 팩토리 메소드를 제거했다.
'Java' 카테고리의 다른 글
타입 및 클래스들 사이에 존재하는 각 종 관계들과 리스코프 치환 원칙 (0) | 2023.03.24 |
---|---|
Java 에서 Stack 구현체로는 무엇을 사용해야할까?(feat_Java로 코딩테스트 문제 풀기) (0) | 2022.09.02 |
[Java] method final parameter ? (0) | 2022.07.27 |
[Java] ImmutableCollection 과 UnmodifiableCollection 과 Immutability (0) | 2022.05.31 |
[Java] 주어진 배열에서 특정 값을 갖는 index 찾기 (stream) (참조글 읽어보기) (0) | 2022.03.08 |