JDK 5 이전에는 열거형을 쓰려면 여러 Enumerate 생성 패턴에 따라 만들어서 썼다. 가장 일반적인 방법은 public static final int로 필드를 선언하는 것이었다.
class Month{
public static final int JAN = 1;
...
}
그러나 이 방법은 Type-Safe 하지 않은 방법이기에 오류가 발생하기 쉬웠다.
심지어 위의 예시의 경우는 숫자로 되어있기에, 1~12의 값이 아닌 13, 심지어 음수까지도 사용할 수 있다. 만약 다른 클래스에서도 동일한 방식으로 선언하는 경우, 서로 다른 클래스간의 비교 연산 또한 아무 문제 없이 가능했다.
이러한 경우를 시스템적으로 제약할 수 없으므로, 버그가 언제든지 생길수 있는 구조다.
출력했을 때도 단순한 숫자값이 찍히므로 유의미한 정보를 얻기가 어려웠다.
그래서 int로 선언하지 않고 아래와 같이 선언하는 방법이 있다.
class Month{
public static final Month JAN = new Month();
...
protected Month(){}
}
위의 코드의 경우는 Type-Safe하지만 Jan의 다음달을 구하는 등의 연산을 처리하기는 어려운 구조이다. 무엇보다 전체 요소를 가져오거나 비교연산을 하는데는 부적합한 구조이다.
class Month{
public static final List MONTHS;
public static final Month JAN;
...
private static final Month[] MONTH_ARRAY;
protected Month(){}
static {
JAN = new Month();
...
MONTH_ARRAY = { JAN, ...};
MONTHS = Collections.unmodifiableList(Arrays.asList(MONTH_ARRAY));
}
}
위의 코드는 내부에 static으로 List의 구현체를 두는 방식으로 위에서 말한 문제점들을 해결했지만, 단순한 기능을 구현하기 위해서 너무 긴 코드를 작성해야 하는 문제가 있었다.
그러나 JDK 5에 들어서 enum을 언어적으로 지원하므로 위처럼 번거로운 작업을 할 필요가 없어졌다.
enum Month{
JAN,
....
}
이제는 Type-safe하며, 출력을 찍었을때 정보를 얻을 수 있고, 번거로운 코드 작업을 할 필요가 없다.
모든 enum 타입은 java.util.Enum을 상속받게끔 되어있고, Enum은 Comparable와 Serializable을 상속받는다. 이로 인해서 abstract class인 Enum에 선언된 name, ordinal등의 메서드를 사용할 수 있다. 또한, 컴파일러에 의해 values, valueOf 메서드가 생성되기 때문에 별다른 코드 작성 없이도 해당하는 기능들을 사용 할 수 있다.
바이트 코드를 기반으로 다시 코드를 작성해보면 아래와 같은 형태를 띄고 있는 것을 알 수 있다.
enum Month extends java.util.Enum<Month>{
public final static Month JAN;
public final static Month FEB;
...
private final static Month[] VALUES;
public static Month[] values(){
return VALUES.clone();
}
public static Month valueOf(String name){
Class clazz = Month.getClass();
return (Month)Enum.valueOf(clazz,name);
}
private Month(String name, int ordinal){
super(name,ordinal);
}
static{
JAN = new Month("JAN",0);
FEB = new Month("FEB",1);
...
VALUES[0] = JAN;
VALUES[1] = FEB;
...
}
}
코드를 복원 해보니 3. List가 포함된 선언방법과 구조가 크게 다르지 않다. 그러나 enum으로 선언하면 저런 번거로운 작업을 컴파일러가 대신 해주는데다가, Comparable, Serializable의 기능까지 사용할 수 있으므로, enum을 사용하는것이 권장된다.