미리 정의된 상수들로 이루어진 제한된 집합을 표현하기 위한 클래스
public static final int JANUARY = 31;
public void printDays(int days) {
System.out.println("Days: " + days);
}
// 메소드 호출
printDays(JANUARY); // 정상 동작
printDays(30); // 논리적으로 잘못된 값이 전달될 수 있음
예를 들어, 1월이 31일까지인데 static final int JANUARY = 31로 선언을 하고, 이 값을 사용하려는 메소드의 파라미터가 int 타입이면, JANUARY를 전달하든, 그냥 31이라는 숫자를 전달하든 메소드는 잘 동작할 것이다. 꼭 31이 아니어도 다른 숫자도 전달할 수 있는데, 그러면 일단 동작은 하겠지만 의도치 않은 결과가 나올 것이다. 이것은 안전하지 않은 방법이다.
public enum Month {
JANUARY(31),
FEBRUARY(28),
MARCH(31),
// ... 다른 월들
;
private final int days;
Month(int days) {
this.days = days;
}
public int getDays() {
return days;
}
}
public void printDays(Month month) {
System.out.println("Days in " + month.name() + ": " + month.getDays());
}
// 메소드 호출
printDays(Month.JANUARY); // 정상 동작
// printDays(31); // 컴파일 에러 발생
하지만 Month라는 enum 클래스를 정의하고 JANUARY(31) 이런 enum 상수를 선언한 다음, 메소드의 파라미터를 Month 타입으로 선언하면 오로지 해당 enum 상수만 인자로 전달 가능하므로 잘못된 인자 전달을 미리 방지할 수 있다.
enum 클래스는 외부에서 객체를 생성하지 못하게 하기 위해서 생성자를 private으로 선언해야 한다. enum은 고정된 상수들의 집합으로 컴파일 타임에 이미 모든 값에 대해 컴파일러가 알고 있다. 그런데 런타임 중간에 다른 객체를 생성한다면 코틀린의 when문이나 자바의 switch-case문에서 예상치 못한 동작을 할 수 있다. (갑자기 else문으로 처리해야 할 일이 생겨버린다.)