본문 바로가기

이펙티브 자바

[이펙티브 자바] 아이템 34. int 상수 대신 열거 타입을 사용하라

열거 타입(Enumeration Type) : 서로 관련된 상수들의 집합을 정의할 때 사용되는 특별한 종류의 클래스. 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입.

 

정수 열거 패턴의 예시 코드 - 취약하다!!

// 정수 열거 패턴 - 안티 패턴
public class Weekdays {
    public static final int MONDAY = 1;
    public static final int TUESDAY = 2;
    public static final int WEDNESDAY = 3;
    // 나머지 요일들도 동일하게 정의

    // 주어진 요일을 출력하는 메서드
    public static String getDay(int day) {
        switch (day) {
            case MONDAY: return "Monday";
            case TUESDAY: return "Tuesday";
            case WEDNESDAY: return "Wednesday";
            // 나머지 요일들에 대한 처리
            default: return "Invalid day";
        }
    }
}

 

 

열거 타입의 예시 : 

// 열거 타입
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    // 주어진 요일을 출력하는 메서드
    public static String getDay(Day day) {
        switch (day) {
            case MONDAY: return "Monday";
            case TUESDAY: return "Tuesday";
            case WEDNESDAY: return "Wednesday";
            // 나머지 요일들에 대한 처리
            default: return "Invalid day";
        }
    }
}

Day day = Day.MONDAY;
System.out.println(Day.getDay(day)); // 출력: Monday

 

전략 열거 타입 패턴 : 각 열거 상수가 서로 다른 동작을 나타내는 열거 타입. 이러한 방식으로 각 상수가 자신만의 동작을 가지며, 열거 타입을 통해 각 동작을 선택할 수 있다.

 

전략 열거 타입 패턴의 예시 코드 : 

// 열거 타입
enum PayrollDay {

	// 주중은 WEEKDAY로 표시되며, 주말은 WEEKEND로 표시된다.
    MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(PayType.WEEKDAY),
    THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURDAY(PayType.WEEKEND),
    SUNDAY(PayType.WEEKEND);
	
    // PayType 열거 상수를 저장하는 private final 필드
    private final PayType payType;

	// PayrollDay의 생성자는 PayType을 받아들여 해당 요일의 지불 방식을 설정한다.
    PayrollDay(PayType payType) {
        this.payType = payType;
    }

    double pay(double hoursWorked, double payRate) {
        return payType.pay(hoursWorked, payRate);
    }

    // 전략 열거 타입 패턴
    enum PayType {
        WEEKDAY {
          double overtimePay(double hours, double payRate) {
              return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT) * payRate / 2;
          }
        },
        WEEKEND {
            double overtimePay(double hours, double payRate) {
                return hours * payRate / 2;
            }
        };

        private static final int HOURS_PER_SHIFT = 8;

        abstract double overtimePay(double hrs, double payRate);

        double pay(double hoursWorked, double payRate) {
            double basePay = hoursWorked * payRate;
            return basePay + overtimePay(hoursWorked, payRate);
        }
    }
}

 

 

핵심 정리 : 열거 타입은 확실히 정수 상수보다 뛰어나다. 더 읽기 쉽고 안전하고 강력하다. 대다수 열거 타입이 명시적 생성자나 메서드 없이 쓰이지만, 각 상수를 특정 데이터와 연결짓거나 상수마다 다르게 동작하게 할 때는 필요하다. 드물게는 하나의 메서드가 상수별로 다르게 동작해야 할 때도 있다. 이런 열거 타입에서는 switch 문 대신 상수별 메서드 구현을 사용하자. 열거 타입 상수 일부가 같은 동작을 공유한다면 전략 열거 타입 패턴을 사용하자.