Enum 열거 타입

YH·2023년 3월 29일
0

✅ 과거의 상수에 대한 정의 방법

✔️ final 상수

  • static과 final을 사용하여 메모리에 한 번만 할당하고, 값이 바뀌지 않도록 하여 상수로 사용
  • 해당 방법은 가독성이 좋지 못함
 class EnumExample {
      private final static int MONDAY = 1;
      private final static int TUESDAY = 2;
      private final static int WEDNESDAY = 3;
      private final static int THURSDAY = 4;
      private final static int FRIDAY = 5;
      private final static int SATURDAY = 6;
      private final static int SUNDAY = 7;
      ...
  }

✔️ interface 상수

  • interface에는 추상 메소드 외에 상수도 선언 가능한데, public static final 속성을 명시하지 않고 사용할 수 있음
  • 그러나, 해당 방법은 다른 집합(인터페이스)의 상수끼리는 비교하면 안되지만, 소스 상에서는 컴파일 에러가 발생하지 않음
  • 또한, 잘못된 상수가 할당되어도 에러가 나지 않으므로, 프로그램 실행 시 원치 않는 방향으로 동작할 수도 있음
interface DAY {
    int MONDAY = 1;
    int TUESDAY = 2;
    int WEDNESDAY = 3;
    int THURSDAY = 4;
    int FRIDAY = 5;
    int SATURDAY = 6;
    int SUNDAY = 7;
}

interface MONTH {
    int JANUARY = 1;
    int FEBRUARY = 2;
    int MARCH = 3;
    int APRIL = 4;
    int MAY = 5;
    int JUNE = 6;
    int JULY = 7;
    int AUGUST = 8;
    int SEPTEMBER = 9;
    int OCTOBER = 10;
    int NOVEMBER = 11;
    int DECEMBER = 12;
}

public static void main(String[] args) {

    int day = DAY.MONDAY;

    // 상수를 비교하는 논리적으로 잘못된 행위를 함으로써 day 변수에 다른 상수값이 들어가버림
    if (DAY.MONDAY == MONTH.JANUARY) {
        // ...
        day = MONTH.JANUARY;
    }

    // day 변수에 있는 상수는 MONTH 상수이기 때문에 조건문에서 걸러져야 되지만,
    // 결국 정수값이기 때문에 에러가 안나고 그대로 수행됨 -> 프로그램 버그 발생 가능성
    switch (day) {
        case DAY.MONDAY:
            System.out.println("월요일 입니다.");
            break;
        case DAY.TUESDAY:
            System.out.println("화요일 입니다.");
            break;
        case DAY.WEDNESDAY:
            System.out.println("수요일 입니다.");
            break;
    }
}

✔️ 자체 클래스 상수

  • 클래스를 사용하여 자체 클래스 인스턴스화 하여 각 객체가 독립된 객체가 되어 상수처럼 활용이 가능함
  • 이렇게 하면 다른 타입의 상수끼리 비교 시 컴파일 에러가 발생하므로 예기치 못한 오류를 방지할 수 있음
  • 그러나, 해당 방법 또한 가독성이 좋지 않고 특히 Switch 문에서 사용할 수 없다는 단점이 있음
class Day {
    // 자기 자신 객체를 인스턴스화 하고 final static 화 함으로써 고유의 객체 상수를 얻게 됨
    public final static Day MONDAY = new Day();
    public final static Day TUESDAY = new Day();
    public final static Day WEDNESDAY = new Day();
}

class Month {
    public final static Month JANUARY = new Month();
    public final static Month FEBRUARY = new Month();
    public final static Month MARCH = new Month();
}

👍 위 방법들의 문제점을 해결하고 다양하게 활용 가능하도록 할 수 있는 것이 Enum 타입이다.

✅ Enum 이란,

✔️ Enumeration의 약자로, 간단히 관련된 상수 데이터들의 집합을 뜻함
✔️ 독립된 특수한 클래스로, Reference 타입으로 분류되어 Heap 영역에 저장되며, enum의 각 상수들은 별개의 메모리 주소 값을 가짐으로써 완벽히 독립된 상수를 구성할 수 있음

✅ Enum의 장점

✔️ 코드가 단순해지며 가독성이 좋아짐
✔️ 허용 가능한 값들을 제한할 수 있음
✔️ enum이라는 키워드로 열거임을 분명하게 나타냄
✔️ Switch 문에서도 사용 가능
✔️ 단순 상수와 비교해 IDE의 적극적인 지원을 받을 수 있음(자동완성, 오타 검증, 텍스트 리팩토링 등)
✔️ 리팩토링 시 변경 범위가 최소화 됨 (Enum 클래스 외에 다른 수정이 필요하지 않음)

✅ Enum 내부 구조

✔️ Enum 클래스는 java.lang.Enum 클래스를 상속 받는데, 실제 동작 내용을 보면 public static final Season SPRING = new Season("SPRING"); 와 같이 각 상수들을 인스턴스화 한다.
✔️ 하지만, Enum 클래스 자체를 인스턴스화 하는 것은 불가능한데, Enum 타입은 런타임이 아닌 컴파일 시 모든 값을 알고 있어야 하기 때문임. 즉 다른 패키지나 클래스에서 enum 타입에 접근해서 값을 할당해주는 것이 금지되어 있음 -> new 키워드로 Enum 클래스 인스턴스 생성이 불가
✔️ 때문에 Enum 클래스의 생성자는 private로 설정해야 함, 결국 Enum 클래스는 final로 볼 수 있음
✔️ Enum 타입은 위와 같은 특성으로 싱글톤(Singleton)을 구현하는 방법 중 하나로 사용되기도 함





참고 Reference

profile
하루하루 꾸준히 포기하지 말고

0개의 댓글