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으로 변환할 때는 알 수 없는 코드의 처리 방식을 정하고, 양방향 변환에 동일한 명시적 매핑을 사용하세요.
숫자 코드가 저장되거나 인터페이스를 통해 전송된 뒤에는 해당 인터페이스에 마이그레이션 절차가 정의되어 있지 않은 한 변경하지 마세요. 기존 데이터의 의미가 이후에도 유지되도록 매핑을 관리하는 곳에 문서화하세요.