상수를 열거 → Enum 사용

상수를 열거하는 것의 단점

// APPLE_ : 사과용 상수
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_BLOOD = 2;

// ORANGE_ : 오렌지용 상수
public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;

1. 각 종류별로 상수들을 구별할 때, Type이 같아서 안정적이지 않다.

위의 예에서 보면 APPLE에 관련된 상수들과 ORANGE에 관련된 상수들의 Type이 int형으로 똑같은 Type이다. 이로 인해 APPLE_FUJI == ORANGE_NAVEL는 아무런 경고 메시지를 출력하지 않고 true를 출력하게 된다.

2. 이름이 겹치는 것을 방지하기 위해, 억지로 접두어를 사용해야 한다.

사과용 상수들에서도 BLOOD가 있고, 오렌지용 상수들에서도 BLOOD가 있다. 하지만 접두어가 없이 똑같이 BLOOD로 선언하면 동일한 이름의 상수가 2개가 되어 에러가 발생한다. 이 때문에 APPLE_BLOOD, ORANGE_BLOOD와 같이 접두어를 써서 이름 충돌을 방지해야 한다. 이 과정은 불필요한 코드를 늘리게 된다.

3. 해당 상수 값을 출력해도 단지 숫자 또는 문자로만 보여서 알아보기가 힘들다.

특히 정수 상수는 문자열로 출력하기가 다소 까다롭다. 그 값을 출력하거나 디버거로 살펴보면 의미가 아닌 단지 숫자로만 보여서 썩 도움이 되지 않는다.

4. 특정 종류의 상수가 몇 개인지 알 수 없다.

특정 종류의 상수를 포함하는 클래스에 속한 모든 상수를 한 바퀴 순회하면서 개수를 세기에도 마땅치 않다. 이로 인해 특저 종류의 상수의 총 개수를 파악하기도 어렵다.

상수를 열거하기 좋은 Enum 타입

public enum Apple {
    FUJI, PIPPIN, BLOOD
}

public enum Orange {
    NAVEL, TEMPLE, BLOOD
}

장점 1. 다른 상수와 겹칠 일이 없음을 보장한다.

Enum 타입 자체는 클래스이며, 상수 하나당 자신의 인스턴스를 하나씩 만들어 public static final 필드로 공개한다. Enum 타입은 밖에서 접근할 수 있는 생성자를 제공하지 않으므로 사실상 final이다. 따라서 클라이언트가 인스턴스를 직접 생성하거나 확장할 수 없으니 Enum 타입의 선언으로 만들어진 인스턴스들은 딱 하나씩만 존재함이 보장된다.

장점 2. 각 종류별로 상수들을 구별할 때, Type이 달라서 안정적이다.

APPLE.BLOODOrange.BLOOD에서 볼 수 있다시피, 각자의 이름 공간이 있어 이름이 같은 상수도 평화롭게 공존한다. 또한 Apple.BLOOD == Orange.BLOOD는 당연히 false가 출력된다.

장점 3. 값을 출력하면 가독성 좋은 문자열로 출력된다.

Enum 타입의 toString 메서드는 출력하기에 적합한 문자열을 내어준다.

장점 4. 특정 종류의 상수가 몇 개인지 알 수 있다.

장점 5. Enum 타입에는 메서드를 추가할 수 있다.

References