34. int 상수 대신 열거 타입을 사용하라

열거 타입은 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입이다.

열거타입을 지원하기 전에는 정수 상수를 한 묶음 선언해서 사용하곤 했다.

public static final int APPLE  = 0;
public static final int BANANA = 1;

정수 열거 패턴 기법에는 단점이 많다.

타입 안전을 보장할 방법이 없으며 표현력도 좋지 않다. 값이 같으면 다른 변수를 보내고 동등 연산자로 비교해도 아무런 경고 메시지를 출력하지 않는다.

정수 열거 패턴을 위한 별도의 Namespace를 지원하지 않기 때문에 접두어를 써서 구분하는데, 이 또한 코드가 지저분해진다.

정수 열거 패턴을 사용한 프로그램은 깨지기 쉽다. 컴파일하면 그 값이 클라이언트 파일에 그대로 새겨진다.

따라서 상수의 값이 바뀌면 클라이언트도 반드시 다시 컴파일해야 한다.

다시 컴파일하지 않은 클라이언트는 실행이 되더라도 엉뚱하게 동작할 것이다.

정수 대신 문자열 상수를 사용하는 변형 패턴도 있지만, 이 패턴은 더 나쁘다. 문자열 값을 하드코딩하게 만들기 때문이다.

하드코딩한 문자열에 오타가 있어도 컴파일러는 확인할 길이 없으니 자연스럽게 런타임 버그가 생긴다.

이러한 패턴들의 단점을 말끔히 씻어주는 동시에 여러 장점을 안겨주는 대안인 열거 타입을 만들어주었다.

public enum Apple { FUJI, PIPPING }

겉보기에는 다른 언어의 열거 타입과 비슷하지만, 자바의 열거 타입은 완전한 형태의 클래스라서 다른 언어의 열거 타입보다 훨씬 강력하다.

자바 열거 타입을 뒷받침하는 아이디어는 단순하다. 열거 타입 자체는 클래스이며, 상수 하나당 자신의 인스턴스를 하나씩 만들어 public static final 필드로 공개한다.

열거 타입은 밖에서 접근할 수 있는 생성자를 제공하지 않으므로 사실상 final이다.

따라서 클라이언트가 인스턴스를 직접 생성하거나 확장할 수 없으니 열거 타입 선언으로 만들어진 인스턴스들은 딱 하나씩만 존재함이 보장된다.

다시 말해 열거 타입은 인스턴스 통제된다.

싱글턴은 원소가 하나뿐인 열거 타입이라 할 수 있고, 거꾸로 열거 타입은 싱글턴을 일반화한 형태라고 볼 수 있다.