Java

🙋‍♂️ 왜 enum 생성자는 자동으로 private로 설정될까?

변위니 2025. 2. 7. 15:02

 

enum을 사용하여 에러 코드를 관리하는 중에 enum의 생성자는 private로 강제되며, 명시적으로 private을 적지 않아도 된다는 부분에 궁금증을 느꼈습니다. 

 

 

문제

@Getter
public enum ErrorCode {

    INVALID_USERNAME(100, "not found username", HttpStatus.NOT_FOUND),
    INVALID_PASSWORD(101, "not found Password", HttpStatus.NOT_FOUND),
    INVALID_AUTHENTICATION(102, "not found username and paassword", HttpStatus.NOT_FOUND),
    NOT_AUTHORIZED(103, "Authorization is missing or invalid", HttpStatus.UNAUTHORIZED);

    private final Integer code;
    private final String message;
    private final HttpStatus status;

    ErrorCode(Integer code, String message, HttpStatus status) {
        this.code = code;
        this.message = message;
        this.status = status;
    }
}

 

enum의 생성자는 자동으로 private로 처리되기 때문에 명시적으로 private를 적지 않아도됩니다.

 

 

 

 

 


궁금한 부분

🙋‍♂️  왜 enum 생성자는 자동으로 private로 설정될까?

위의 글을 보면 enum의 상수는 정의될 때 생성자를 통해 전달된 값으로 초기화되며, 상수를 필드와 메서드를 정의하기 전!!! 맨 위에 정의해야 한다고 합니다. enum생성자는 package-private, private로만 접근이 가능하고, 직접 enum 객체를 생성할 수 없습니다. 

 


 

 

위의 질문에 대한 답을 찾기 전에 아래 질문에 대한 답을 찾아보겠습니다.

 

🙋‍♂️ enum에서의 상수는 왜 선언부에 정의되어야 할까?

enum 상수는 단순한 값이 아닌 각각 객체로 생성됩니다. JVM이 enum 클래스를 메모리에 올릴 때, 모든 상수를 생성자 호출을 통해 객체로 초기화합니다. 각 상수를 객체로 초기화하기 때문에, 상수 선언 순서가 중요합니다. 

정적 초기화의 목적은 클래스나 인터페이스가 일관된 상태로 초기화되도록 보장하는 것입니다. 즉, 다른 클래스가 해당 클래스를 사용할 때, 일관된 초기화 상태를 항상 보장해야 합니다.

자바에서는 정적 초기화가 소스 코드의 텍스트 순서로 실행되고, 초기화 시점에서 아직 초기화되지 않은 변수는 참조할 수 없습니다. 

즉, 초기화가 텍스트 순서에 따라서 실행되기 때문에, 잘못된 순서로 변수나 메서드에 참조할 경우에 컴파일러가 사전에 감지해 컴파일 오류를 발생시킵니다.

 

따라서, enum 상수는 반드시 먼저 초기화된 후에 필드나 메서드에서 이를 참조해야 합니다.


 

수가 생성되는 흐름을 간략히 살펴 보겠습니다.

 

1. 가장 먼저 상수를 선언합니다.

모든 상수는 enum의 선언부 맨 위에 있어야 하고, 컴파일 시점에 메모리에 할당됩니다.

INVALID_USERNAME(100, "not found username", HttpStatus.NOT_FOUND),

 

2. 상수를 생성합니다.
각 상수는 컴파일러에 의해 자동으로 ErrorCode 생성자 호출로 변환됩니다.

public static final ErrorCode INVALID_USERNAME = new ErrorCode(100, "not found username", HttpStatus.NOT_FOUND);

 

3. 생성자를 호출합니다.
각 상수의 값이 생성자에 전달되어 초기화합니다. 

ErrorCode(Integer code, String message, HttpStatus status) {
    this.code = code;
    this.message = message;
    this.status = status;
}

 


 

 

그럼 이제 처음의 질문으로 돌아가겠습니다.

 

 

enum 생성자가 private로 설정되는 이유는 무엇일까?

enum 생성자가 private인 이유는 객체를 내부에서 직접 생성하여, 미리 정의된 값으로만 사용할 수 있도록 보장하기 위함입니다. 이를 통해 외부에서 임의의 새로운 객체를 생성하는 것을 차단하여 상수의 일관성을 유지할 수 있습니다.

만약 외부에서 객체를 생성할 수 있다면, 정의된 상수 외에 객체가 생성되어 일관성이 깨질 수 있기 때문에, 자바 컴파일러에서는 enum 의 생성자를 private으로 강제합니다. 

 

 

 

 

 

 

 

 

 

[참고]