HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
WhiteShip-LiveStudy
WhiteShip-LiveStudy
/
11주차 과제: Enum
11주차 과제: Enum
11주차 과제: Enum

11주차 과제: Enum

  • EnumSet
 
@) 참고
The Java™ Tutorials - Enum Types
Java Language Specification - Chaper 8.9. Enums

Enum의 기본 개념

enum type 은 predefined 된 상수를 표현하기위한 특별한 데이터타입이다. 변수는 무적권 predefined된 값중 하나와 같아야한다.
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; }
java.lang.Thread.State enum 으로 정의된 쓰레드의 상태 Thread.State 역시 상수만을 가짐
enum은 클래스 이지만 클래스의 내부에 public으로 선언 될 수 있다.
Thread.State terminated = Thread.State.TERMINATED;
Thread.State를 사용하는 방법

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; } ... }
org.springframwork.lang.HttpStatus
  • 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); ... }
      org.springframework.lang.HttpStatus.Series

 
이펙티브 자바에 나오는 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 Example 8.9.2-4. Enum Constants with Class Bodies @Language Spec

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 클래스의 상속 → 컴파일 타임 에러
    • Classes cannot directly extend 'java.lang.Enum’
      Classes cannot directly extend 'java.lang.Enum’
  • 이 클래스에 enum이 제공하는 메서드인 ordinal( ) 등이 정의되어 있다.
  • enum을 프린트 찍었을때 나오는 값이 각 상수의 이름이 되는 이유는 java.lang.Enum이 toString을 override하였기 때문이다.
  • 해당 클래스에 정의된 final clone 메서드, serialization 방지 메커니즘, 상속 방지 메커니즘 등을 통해 enum사용 하여 간단하게 singleton 패턴을 높은 수준까지 구현할 수 있다.
  • See Also)
1️⃣
Singleton Pattern
 

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