Java Enum이란?

허진혁·2023년 7월 6일
0

기본기를 다지자

목록 보기
2/10

🧭 목적

enum은 무엇이고 왜 사용할까요?
enum을 이해해보고
enum의 내부 동작원리를 메모리 관점으로
공부하며 진행해 볼게요 !!

🤔 enum은 무엇일까?

enum은 상수들의 집합이에요. enum을 설명할 때 대표적인 예시로 요일이 있어요. "월, 화, 수, 목, 금, 토, 일"처럼 한정된 데이터를 계속해서 사용할 때 Enumeration 타입을 사용해요.

Enumberation(열거형) 타입을 enum 데이터 타입이라 하고, 그 안에 데이터들을 열거형 상수라고 해요.

관례로 상수는 대문자로 표기하며 띄어쓰기는 "_"를 사용해요. enum 데이터 타입도 클래스를 정의할 때와 마찬가지로 정의하면 되요.

public enum Week {
    MONDAY,
    TUSEDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY;
}

🙆 enum 내부 동작 원리

enum은 클래스로 컴파일되며, 내부적으로 특별하게 저장이 되요.

enum 클래스의 부모는 java.lang.Enum 이에요.

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    /**
     * The name of this enum constant, as declared in the enum declaration.
     */
    private final String name;

    /**
     * The ordinal of this enumeration constant (its position
     * in the enum declaration, where the initial constant is assigned
     * an ordinal of zero).
     */
    private final int ordinal;

    /**
     * Sole constructor.  Programmers cannot invoke this constructor.
     * It is for use by code emitted by the compiler in response to
     * enum type declarations.
     *
     * @param name - The name of this enum constant, which is the identifier
     *               used to declare it.
     * @param ordinal - The ordinal of this enumeration constant (its position
     *         in the enum declaration, where the initial constant is assigned
     *         an ordinal of zero).
     */
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
    // ...
}

protect Enum(String name, int ordinal) 라는 부모 생성자가 있으며, name은 상수 이름, ordinal은 상수가 선언된 순서로 0부터 증가하는 구조에요.

자바의 enum은 Enum 클래스를 직접 상속하는 것이 아니라, 컴파일러가 컴파일 과정에서 Enum 클래스를 상속받도록 처리되요.

⚙️ 메모리 관점으로 파악하기

1️⃣ enum은 heap 메모리에 생성되요.

자바 enum은 클래스로 컴파일되어 Enum 인스턴스는 일반적인 객체와 마찬가지로 heap 메모리에 생성되요.

2️⃣ enme 상수들은 고정된 인스턴스로서 스태틱 필드에 정의되요.

enum 상수는 해당 enum 타입의 유일한 인스턴스로 존재하며, 상수들은 enum 정의 시점에서 생성되요.

이러한 인스턴스들은 enum 클래스의 스태틱 필드로 정적 초기화되며, enum 클래스의 생성자에서 상수의 초기화 작업이 진행되요.

그러므로 enum은 미리 정의된 상수 인스턴스들을 가지고 있기 때문에 enum 상수를 사용할 때마다 새로운 인스턴스를 생성하지 않아요.

Enum 클래스가 제공하는 메소드

name() 함수를 통해 상수의 이름을,
ordinal() 함수를 통해 상수의 선언 순서를 알 수 있어요.

이 외에 중요하게 보아야 할 것이 있어요.

모든 클래스의 최상위 부모클래스는 Object에요.

우선 equals()와 hashCode()는 사용할 수 있고, 재정의할 수 있어요. equals()와 hashCode() 메소드는 객체의 동등성 비교와 해시 계산에 관련된 중요한 메소드이며, enum 객체 간의 동등성과 해시 계산을 정확하게 처리하기 위해 오버라이딩할 수 있도록 허용했어요.

그런데, clone()과 finalize()는 오버라이딩이 불가능해요.

clone() 메소드는 말 그대로 객체를 복사하기 위해 사용하는 것인데, enum은 상수의 집합. 즉, 이미 enum 정의 시점에 생성되고 변경되지 않아요.

그래서 복사하는 것 자체가 의미가 없을 뿐더러, 오히려 복제되면 상수의 중요한 특징인 일관성을 해치게 되요. 그래서 오버라이딩을 불가하게 해두었어요.

finalize() 메소드는 객체가 GC 되기 전에 호출되는 메소드에요. 즉, GC 이전에 객체를 정리하는 것인데, 이는 호출 타이밍에 대한 보장이 없고, 성능 저하 가능성이 있고, 안정성과 예측 가능성의 문제 등 떄문에 자바에서 권장하지 않아요.

enum 클래스에서 finalize() 메소드를 오버라이딩할 수 없는 이유는 finalize() 메소드의 위험성과 안정성 문제 때문이며, enum이 특별하다기 보다 자바 자체에서 권장하지 않아서 그런거 같아요.

정리

1️⃣ enum은 상수들의 집합이며,

2️⃣ enum은 Enum 클래스를 직접적인 상속이 아니라, 컴파일 과정에서 상속받도록 처리되고,

3️⃣ enum은 heap 메모리에 생성되며,

4️⃣ enum 안의 상수들은 enum의 정의 시점에 스태틱 필드에 초기화되고

5️⃣ enum 클래스는 clone()과 finalize() 메서드를 상속할 수 없어요.

참고자료

자바의 신

profile
Don't ever say it's over if I'm breathing

0개의 댓글