ordinal
- 대부분의 열거 타입 상수는 자연스럽게 하나의 정수와 대응됩니다. 그리고 모든 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는
ordinal
이라는 메서드를 제공합니다.
- 만약 enum에
APPLE
, GRAPE
가 존재할 때 APPLE
의 ordinal
은 1인 꼴입니다.
- 이런 이유로 열거 타입 상수와 연결된 정수값이 필요할 시
ordinal
을 사용하려는 생각이 들 수 있으나 이런 방식은 심각한 문제를 일으킬 수 있습니다.
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() {
return ordinal() + 1;
}
}
- 위의 코드에서 상수 선언 순서를 바꾸면 어떻게 될까요? 예를 들어 위의
SOLO
와 DUET
을 바꾸는 방식입니다.
- 이 둘의 위치값이 바뀌기 때문에
numberOfMusicians
는 전혀 다른 값을 내놓게 될 것입니다.
- 또한 이미 사용 중인 정수와 값이 동일한 상수는 추가할 방법이 없습니다. 8명이 연주하는 다른 상수를 넣고 싶은데 이미 8명이 연주하는
OCTET
이 존재하니 추가할 수 없기 때문입니다.
- 또한 값을 중간에 비워둘 수도 없습니다. 연속되어 들어가기 때문에 12명이 연주하는 상수를 넣고 싶다면 11명이 연주하는 상수도 같이 추가해야 합니다.
- 11명이 연주하는 방식은 없기 때문에 이는 자연스럽게
DUMMY
로 들어가야 하며 이런 방식은 실용성도 없고 코드 역시 깔끔하지 못합니다.
- 이런 이유로 열거 타입 상수에 연결된 값들은
ordinal
로 얻는 것이 아닌 인스턴스 필드에 저장해야 합니다.
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), NONET(9), DECTET(10);
private final number;
Ensemble(int number) {
this.number = number;
}
public int numberOfMusicians() {
return number;
}
}
- Enum의 API 문서에도
ordinal
은 EnumSet
과 EnumMap
과 같이 열거 타입 기반의 범용 자료구조에 쓸 목적으로 설계되었다고 되어 있습니다. 따라서 이런 목적으로 사용하는 것이 아니라면 ordinal
메서드는 사용하지 말아야 합니다.