- EnumSet
@) 참고
Enum의 기본 개념
enum type 은 predefined 된 상수를 표현하기위한 특별한 데이터타입이다. 변수는 무적권 predefined된 값중 하나와 같아야한다.
- Enum의
EnumConstant
를 대문자로 작성하는 것은 자바의 컨벤션 중 상수를 대문자로 작성하는 것과 일관성을 갖는다.
- Enum type은
enum
키워드로 정의한다.
public enum Day { SUNDAY, MONDAY, THUSDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
- Enum type은 고정된 상수 집합을 표현하기 위해 사용한다
- 이들은 컴파일 타임에 모든 관련된 값 들을 추론 할 수 있다.
- e.g.) 태양계의 행성 집합, 메뉴의 Choice, 쓰레드의 상태, HTTP의 상태코드, 사칙 연산
Let’s see some code!
public class DayMain{ public static void main(String[] args) { printMyFavorDays(Day.MONDAY); } private static void printMyFavorDays(Day day) { switch (day) { case MONDAY: System.out.println("I HATE MONDAY"); break; case THURSDAY: System.out.println("I LOVE THURSDAY"); break; default: System.out.println("I LIKE OTHER DAYS"); break; } } enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY; } }
enum
public enum state { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
enum
으로 정의된 쓰레드의 상태 Thread.State
역시 상수만을 가짐 enum은 클래스 이지만 클래스의 내부에
public
으로 선언 될 수 있다.Thread.State terminated = Thread.State.TERMINATED;
public enum HttpStatus { OK(200, "OK"), CREATED(201, "Created"), ... INTERNAL_SERVER_ERROR(500, "Internal Server Error"), ... private final int value; private final String reasonPhrease; ... public static HttpStatus valueOf(int statusCode) { HttpStatus status = resolve(statusCode); if (status == null) { throw new IllegalArgumentException("No matching constant for [" + statusCode + "]"); } else { return status; } } ... public boolean is2xxSuccessful() { return this.series() == HttpStatus.Series.SUCCESSFUL; } ... }
- Http의 상태코드를 저장하는 enum
value
와reasonPhrase
두가지 필드를 가지고 있음
statusCode
로 enum을 찾아주는valueOf
메서드 제공
- nXX대 상태 코드 (Series) 인지 확인하는
isNxxRepresentationalPhrase
메서드 제공
- 내부에 상태코드의 Series를 표현하는 enum을 가짐
public static enum Series { INFORMATIONAL(1), SUCCESSFUL(2), REDIRECTION(3), CLIENT_ERROR(4), SERVER_ERROR(5); ... }
이펙티브 자바에 나오는 Enum의 사용예제 Item 34
public enum Operation { PLUS { public double apply(double x, double y) { return x + y; } }, MINUS { public double apply(double x, double y) { return x - y; } }, TIMES { public double apply(double x, double y) { return x * y; } }, DIVIDE { public double apply(double x, double y) { return x / y; } }; public abstract double apply(double x, double y); }
Enum 활용시 주의 사항
enum이 추상 메서드를 가지면 상수의 선언시에 구현부를 작성해주어야 한다.
위 예제의 경우 추상 메서드 대신 biFunction<Double, Double> 을 필드로 가지게 한다면 더욱 간결한 코드를 유지할 수 있다.
또한 하지만 위와 같은 연산 로직의 enum을 활용한 구현은 연산 로직과 Operation이라는 enum 즉 일종의 추상타입이 강하게 결합되는 단점이 있다.
EXPONENTIAL이라는 연산 로직을 하나 추가한다고 했을때 위의 경우 모든 연산 로직이 담겨 있는 Operation enum자체에 대한 변경이 불가피 하다.
Operation 을 추상클래스로 변경하면 그 결합도를 줄이고 수 있다. Operation의 구현체인 Exponential 클래스를 추가하는 것 만으로 기능을 추가할 수 있다.
이런 컴파일 타임에서의 강한 결합도는 enum을 활용할때 주의해야할 사항이다.
enum 정의하는 방법
ClassModifiersopt enum Identifier Interfacesopt EnumBody EnumBody: { EnumConstantsopt ,opt EnumBodyDeclarationsopt }
- enum 키워드를 사용하여 정의한다.
- 흔히 사용되지는 않지만 enum이 interface를 구현할 수 있다는 점이 눈에 띈다.
- enum type은 절대루 abstract로 선언될 수 없다. → 컴파일 타임 에러
- enum type은 implicit하게 final이다.
- explicit하게 final 이라고 작성 → 컴파일 타임 에러
- Nested enum types 는 implicit 하게
static
이다. - 따라서 local enum 혹은 inner class에 enum을 정의 할 수 없다.
java.lang.Enum
- 모든 enum은 자동으로 추상클래스
java.lang.Enum
을 상속한다. - 정확하게는
java.lang.Enum<E>
- explicit한 Enum 클래스의 상속 → 컴파일 타임 에러

- 이 클래스에 enum이 제공하는 메서드인
ordinal( )
등이 정의되어 있다.
- enum을 프린트 찍었을때 나오는 값이 각 상수의 이름이 되는 이유는 java.lang.Enum이
toString
을 override하였기 때문이다.
- 해당 클래스에 정의된 final clone 메서드, serialization 방지 메커니즘, 상속 방지 메커니즘 등을 통해 enum사용 하여 간단하게 singleton 패턴을 높은 수준까지 구현할 수 있다.
- See Also)
enum이 제공하는 메소드
- enum은 대표적으로 세가지 메서드를 제공한다.
ordinal( ) | 해당 값이 enum에 정의된 순서를 리턴. |
values( ) | enum의 요소들을 순서대로 enum타입의 배열로 리턴. |
valueOf( ) | String 값을 enum에서 가져옴. 값이 없으면 예외 발생 |
- ordinal( ) 의 사용은 지양해야한다.
- ordinal( )을 사용하여 로직을 작성하면 Enum이 정의된 순서에 클라이언트의 로직이 의존한다는 것을 의미한다.
- See - 이펙티브 자바 Item 35, 37
- values 메서드
- 특이하게 values는 어디에도 정의 되어 있지 않다.
- java.lang.Enum의 document를 Compiler가 Implicit하게 해당 메서드를 추가한다는 내용이 있다.
- 정확한 구현방식은 확인을 못했지만 해당 메서드도 배열을 생성하는 방식이 효율적이지 않은것 같다. 잦은 사용은 지양하자. 필요하면 써야됨
- See also)
EnumSet
,EnumMap
Day[] values = Day.values();
- valueOf 메서드
- valueOf 메서드는 두가지 선언방식을 가진다.
T
valueOf
(String)
T
valueOf
(Class<T>, String)
- 이중 위의 메서드도
values
메서드와 마찬가지로 compiler에 의해 implicit하게 추가된다. - 적절한 Enum 타입을 찾지 못하면
IllegalArgumentException
를 던진다. - 적절한 필드를 사용해 valueOf를 overloading하여 사용할 수 도 있다.
- 위 예시의
HttpStatus.valuOf(int statusCode)
EnumSet/ EnumMap
Note that when using an enumeration type as the type of a set or as the type of the keys in a map, specialized and efficientset
andmap
implementations are available. - javadoc @java.lang.Enum

EnumSet은 추상 클래스이며, 인스턴스 생성을 위한 다양한 정적 팩토리 메서드가 정의되어있다. JDK에서는 RegularEnumSet, JumboEnumSet 2가지의 EnumSet 구현체를 제공한다.
EnumSet의 모든 메서드(contains 등)는 산술 비트 연산을 사용하여 구현되므로 일반적인 연산이 매우 빠르게 계산된다.
EnumSet은 HashSet 같은 다른 Set 구현체와 비교했을 때, 데이터가 예상 가능한 순서로 저장되어 있고, 각 계산을 하는데 하나의 비트만이 필요하므로 더 빠르다고 할 수 있다. 또한 HashSet 처럼 데이터를 저장할 버킷을 찾는 데 hashcode를 계산할 필요가 없다.
더욱이 EnumSet은 비트 벡터의 특성상 더 작은 메모리를 사용한다.