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

열거 패턴

  • 자바에서 열거 타입을 지원하기 전에는 정수 상수를 한 묶음으로 선언해 사용하였다.

  • 타입 안전을 보장할 수 없고, 표현력이 좋지 않다.

  • 컴파일하면 값이 클라이언트 파일에 그대로 넘겨지기 때문에 상수의 값이 변경되면 클라이언트도 다시 컴파일 해야 한다.

public static final int GREEN_APPLE = 0;
public static final int RED_APPLE = 1;
public static final int COMPANY_APPLE = 2;
...

열거 타입

  • 완전한 형태의 클래스이다.

  • 상수 하나 당 인스턴스를 하나씩만 만들어 public static final 필드로 공개한다.

  • 인스턴스를 하나만 만들기 때문에 싱글톤을 일반화한 형태라고 볼 수 있다.

  • 컴파일타임 타입 안전성을 제공하여 타입이 다른 변수를 할당하려 할 때 컴파일 오류가 발생한다.

  • 필요한 원소를 컴파일타임에 전부 알 수 있는 상수 집합일 때 사용하도록 한다.

  • 추후 상수가 추가되어도 바이너리 수준에서 호환되므로 정의된 상수 개수가 영원히 고정 불변일 필요는 없다.

열거 타입과 메서드, 필드

  • 특정 데이터와 열거 타입 상수를 연결지으려면 생성자에서 데이터를 받아 인스턴스 필드에 저장하면 된다.

  • 열거 타입에 선언한 상수 하나를 제거하더라도 제거한 상수를 참조하지 않는 클라이언트에는 아무 영향이 없다. 제거된 상수를 참조하면 컴파일 에러가 발생할 것이다.

데이터와 메서드를 갖는 열거 타입

  • 열거 타입에는 임의의 메소드나 필드를 추가할 수 있고 임의의 인터페이스를 구현하게 할 수도 있다.

  • 아래는 생성자에서 데이터를 받아 인스턴스 필드에 특정 데이터를 저장하여 연결한 예제이다.

  • 열거 타입은 불변이므로, 모든 필드는 final이어야 한다.

  • 최적화를 위해 surfaceGravity를 미리 계산해 저장해둘 수도 있다.

  • values() : 자신 안에 정의된 상수들의 값을 배열에 담아 반환하는 정적 메서드

  • 열거 타입에서 상수를 제거하는 경우, 클라이언트 프로그램을 다시 컴파일하면 컴파일 에러가 발생하고, 다시 컴파일하지 않으면 런타임 예외가 발생하여 정수 열거 패턴에 비해 훨씬 쉽게 디버깅할 수 있다.

상수별 메서드 구현

  • 상수마다 동작이 달라져야 하는 상황일 때 사용한다.

  • 하나의 메서드를 사용하는 것이 아닌, 열거 타입에 추상 메서드를 선언하고 각 상수에서 재정의하도록 한다.

열거 타입 용 fromString 메서드

  • toString이 반환하는 문자열을 해당 열거 타입 상수로 변환해주는 메서드

  • Optional로 반환하여 값이 존재하지않을 상황을 클라이언트에게 알린다.

  • stringToEnum을 생성자 외부에서 초기화하는 이유는 열거 타입에서 정적 필드가 열거 타입 상수를 생성한 후 초기화 되기 때문이다. 다시 말하자면 열거 타입 생성자에서 정적 필드인 stringToEnum을 참조해 본인 인스턴스를 추가하려고 하면, 아직 stringToEnum이 초기화되지 않은 상태이기 때문에 컴파일 에러가 발생할 것이다.

전략 열거 타입 패턴

  • 상수별 메서드 구현 시 열거 타입 상수끼리 코드를 공유하기 어렵다.

  • switch문으로 상수별 사용할 로직을 다르게 지정할 수 있지만, 새로운 상수를 추가하면 메서드를 재정의해야 한다는 문제가 있다.

  • 새로운 상수를 추가할 때 마다 전략을 선택하도록 한다. 전략 열거 타입을 하위에 지정하고 필요한 로직을 위임하여 사용한다.

  • swithch문이나 상수별 메서드 구현이 필요 없게 되고, switch 문보다 복잡하지만 더 안전하고 유연하다.

  • 아래의 예제는 잔업 수당 계산하는 로직을 private 전략 열거 타입에 두고, PayrollDay 열거 타입이 잔업수당 계산 필요 시 전략 열거 타입이 로직을 수행한다.

  • 다만, 기존 열거 타입에 상수별 동작을 혼합해 넣을 때에는 switch 문이 좋다.

Last updated