(Effective Java 2/E) 137. Item 31 - Use instance fields instead of ordinals

Use instance fields instead of ordinals

  • 2판 제목 : ordinal 대신 객체 필드를 사용하라
  • 3판 제목 : ordinal 메서드 대신 인스턴스 필드를 사용하라

1. ordinal

대부분의 enum 상수는 자연스럽게 int값 하나에 대응된다.

모든 enum에는 ordinal이라는 메서드가 있으며, 이 메서드는 자료형 안에서 enum 상수의 위치를 정수 형태로 반환한다.

예를 들면 아래와 같다.

1
2
3
4
5
6
7
8
9
// Abuse of ordinal to derive an associated value - DON'T DO THIS
public enum Ensemble {
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SEPTET, OCTET, NONET, DECTET;

public int numberOfMusicians() {
return ordinal() + 1;
}
}

이 코드는 동작엔 문제가 없다.

하지만 순서가 바뀌거나 상수가 추가되면 기존 동작을 보장할 수 없는 코드이다.

2. instance field

원칙적으로 enum 상수에 연계되는 값은 ordinal()을 쓰면 안되며,

연계되는 값은 객체 필드(instance field) 에 저장해야한다.

위의 예제를 아래와 같이 변경해보자.

1
2
3
4
5
6
7
8
9
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SEPTET(7), OCTET(8), DOUBLE_QUARTET(8),
NONET(9), DECTET(10), TRIPLE_QUARTET(12);

private final int numberOfMusicians;
Ensemble(int size) { this.numberOfMusicians = size; }
public int numberOfMusicians() { return numberOfMusicians; }
}

각 상수가 별도의 값을 가지고 있으므로, 이제 문제 없이 동작할 수 있다.

3. Purpose of ordinary

그렇다면 ordinal()은 쓰면 안되는 메서드일까?

공식 문서에서 ordinal()의 정의를 보면 아래와 같다.

Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

즉 일반적인 용도로 사용할 일은 거의 없을 것이며, EnumSet이나 EnumMap처럼 enum기반 자료 구조에서 사용할 목적으로 설계되어 있음을 알 수 있다.

References