HOWTO · Java

Java에서 Enum을 Int로 변환

이 튜토리얼은 Java에서 Enum을 Int로 변환하는 방법을 보여줍니다.

이 페이지의 내용

Java의 ordinal()는 enum 상수가 선언된 순서를 기준으로 한 0부터 시작하는 위치를 반환합니다. 상수가 바뀌어도 같은 의미를 유지해야 하는 숫자라면 enum에 정수를 명시하거나 별도의 Map을 유지하세요. 적절한 방법은 데이터가 선언 위치, 안정적인 코드, 외부 매핑 중 무엇을 나타내는지에 따라 달라집니다.

ordinal()로 enum 상수를 int로 변환하기

모든 enum 상수에는 ordinal() 값이 있습니다. 먼저 선언된 상수는 0, 다음 상수는 1이며 이후에도 같은 방식으로 이어집니다. 한 프로그램 안에서 임시 인덱스로 쓰는 경우처럼 선언 위치 자체가 의미 있을 때 유용합니다. 하지만 저장된 데이터나 공개 인터페이스에는 취약합니다. 상수를 삽입하거나 순서를 바꾸면 이후 값이 달라지므로, ordinal 값을 범용 코드처럼 사용하지 마세요. Java SE Enum API 문서는 이 값이 선언 순서에서 해당 상수가 차지하는 위치라고 정의하며, 대부분의 프로그래머에게 이 메서드가 필요하지 않다고 설명합니다. 따라서 범용 코드로 사용하는 데는 제한이 있습니다.

다음 예제를 실행하세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class EnumOrdinalExample {
  enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY }

  public static void main(String[] args) {
    int position = Day.WEDNESDAY.ordinal();
    System.out.println("WEDNESDAY position: " + position);
  }
}

관찰된 출력:

WEDNESDAY position: 3

사용자 정의 enum 필드로 안정적인 정수 할당하기

각 상수에 안정적으로 유지할 정수 코드가 있다면 명시적인 필드를 지정하세요. 생성자가 값을 한 번 할당하고 getter가 그 값을 제공합니다. 상수의 순서를 바꿔도 숫자는 달라지지 않습니다. 다만 숫자를 변경하면 매핑이 바뀌므로, 이미 저장했거나 다른 시스템과 주고받는 코드는 해당 시스템의 계약으로 취급해야 합니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class EnumCodeExample {
  enum Day {
    SUNDAY(10), MONDAY(20), WEDNESDAY(40);

    private final int code;

    Day(int code) {
      this.code = code;
    }

    int code() {
      return code;
    }
  }

  public static void main(String[] args) {
    int code = Day.WEDNESDAY.code();
    System.out.println("WEDNESDAY code: " + code);
  }
}

값은 ordinal 위치와 의도적으로 다르게 지정합니다. 매핑은 enum이 관리하므로 호출자는 선언 순서에 의존하는 대신 Day.WEDNESDAY.code()를 사용합니다.

매핑이 enum 외부에 있을 때 Map 사용하기

주변 구성 요소처럼 enum과 별도로 연결 관계를 설정하거나 관리한다면 Map<Day, Integer>를 사용하세요. 반환된 Integer를 기본형으로 변환하기 전에 키가 없는 경우를 확인해야 합니다. Map.get은 매핑이 없으면 null을 반환하며, 이 결과를 바로 int에 할당하면 실행 중 오류가 발생합니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import java.util.HashMap;
import java.util.Map;

public class EnumMapExample {
  enum Day { SUNDAY, MONDAY, WEDNESDAY }

  public static void main(String[] args) {
    Map<Day, Integer> codes = new HashMap<>();
    codes.put(Day.SUNDAY, 10);
    codes.put(Day.MONDAY, 20);
    codes.put(Day.WEDNESDAY, 40);

    Integer code = codes.get(Day.WEDNESDAY);
    if (code != null) {
      System.out.println("WEDNESDAY code: " + code);
    }
  }
}

enum 키를 사용하면 키 이름을 잘못 입력하는 일을 막을 수 있지만, 항목을 채우고 관리할 책임은 맵의 소유자에게 있습니다. 모든 상수에 항상 동일한 고정 매핑을 적용한다면 enum 필드로 상수와 매핑을 함께 관리할 수 있습니다.

int를 다시 enum으로 변환하기

명시적 코드가 있다고 해서 자동 역변환이 제공되는 것은 아닙니다. 일치하는 필드를 가진 enum 상수를 검색하고, 알 수 없는 정수에 어떤 결과를 적용할지 정하세요. 이 예제는 일치하는 값이 없으면 null을 반환합니다. 다른 정책이 필요하다면 호출자가 Optional<Day>를 반환하거나 경계에서 오류를 보고할 수 있습니다.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

public class EnumReverseExample {
  enum Day {
    SUNDAY(10), MONDAY(20), WEDNESDAY(40);

    final int code;

    Day(int code) {
      this.code = code;
    }

    static Day fromCode(int code) {
      for (Day day : values()) {
        if (day.code == code) {
          return day;
        }
      }
      return null;
    }
  }

  public static void main(String[] args) {
    Day day = Day.fromCode(40);
    if (day != null) {
      System.out.println("Code 40: " + day.name());
    }
  }
}

상수가 적은 enum에서는 values()를 순회하는 방법이 간단합니다. 역조회가 자주 발생하거나 enum이 크다면 역방향 맵을 한 번 만들어 사용하고, 중복 코드가 잘못된 상수를 조용히 선택하는 일이 없도록 하세요.

valueOf()가 하는 일과 하지 않는 일

Day.valueOf("WEDNESDAY")는 선언된 이름이 문자열과 정확히 일치하는 enum 상수를 찾습니다. 반환값은 정수가 아니라 Day입니다. 그 뒤에 .ordinal()를 호출하면 Day.WEDNESDAY.ordinal()와 같은 선언 순서 기준의 숫자가 나옵니다. valueOf()를 호출해도 그 ordinal 값은 안정적으로 유지되지 않습니다. 이름 조회는 대소문자를 구분하고 일치하는 이름이 있어야 하므로, 임의의 숫자 코드가 아니라 이미 알고 있는 enum 이름을 변환할 때 적합합니다.

데이터에 맞는 매핑 선택하기

  • 선언 위치 자체가 의도한 값이고 숫자가 지속적으로 사용될 외부 코드가 아닐 때만 ordinal()를 사용하세요.
  • 각 상수에 고정된 숫자 의미가 있다면 사용자 정의 enum 필드를 사용하세요. 매핑을 enum과 함께 관리하므로 안정적인 코드에 대체로 가장 명확한 선택입니다.
  • 다른 구성 요소가 매핑을 소유하거나 매핑을 별도로 불러와 관리한다면 Map을 사용하세요. 항목이 없는 경우를 명시적으로 처리해야 합니다.
  • 정수에서 enum으로 변환할 때는 알 수 없는 코드의 처리 방식을 정하고, 양방향 변환에 동일한 명시적 매핑을 사용하세요.

숫자 코드가 저장되거나 인터페이스를 통해 전송된 뒤에는 해당 인터페이스에 마이그레이션 절차가 정의되어 있지 않은 한 변경하지 마세요. 기존 데이터의 의미가 이후에도 유지되도록 매핑을 관리하는 곳에 문서화하세요.