Java

열거형(enum)

1space 2025. 6. 26. 07:45

자바의 정석[기초편]으로 공부한 내용을 정리한 글입니다.

열거형이란?

  • 여러 개의 상수를 정의할 때, 각각 static final로 정의하는 대신 한 번에 묶어서 선언할 수 있는 방식입니다.
  • 예: 카드의 무늬(CLOVER, HEART 등)와 숫자(TWO, THREE 등)처럼 고정된 값들의 집합을 만들 때 적합합니다.

기존 방식 (불편하고 길다)

enum 열거형이름 { 상수1, 상수class Card {
    static final int CLOVER = 0;
    static final int HEART = 1;
    static final int DIAMOND = 2;
    static final int SPADE = 3;

    static final int TWO = 0;
    static final int THREE = 1;
    static final int FOUR = 2;

    final int kind;
    final int num;
}
2, 상수3, ... }
  • 모든 상수값은 int로 정의됩니다.
  • 숫자값이 같더라도 구분이 안 됩니다. (CLOVER == TWO → true)
  • 문제점: 어떤 값이 어떤 의미인지 코드만 봐선 알기 어렵고, 타입 안전성(type safety)도 떨어집니다.

enum 사용 (간결하고 타입 안정성 보장)

class Card {
    enum Kind { CLOVER, HEART, DIAMOND, SPADE }
    enum Value { TWO, THREE, FOUR }

    final Kind kind;
    final Value value;
}
  • enum Kind는 무늬에 대한 열거형, enum Value는 숫자에 대한 열거형입니다.
  • 이제 kind는 Kind 타입이고, value는 Value 타입이므로 서로 다른 타입으로 비교됩니다.

장점:

  • Card.Kind.CLOVER == Card.Value.TWO → 컴파일 에러 발생
    • 타입이 다르므로 비교 자체가 불가능!
  • 타입 안전성(type safety) 확보됨
  • 코드가 간결하고 읽기 쉬움

 

열거형의 정의와 사용

열거형(enum) 선언 방식

enum 열거형이름 { 상수1, 상수2, 상수3, ... }
enum Direction { EAST, SOUTH, WEST, NORTH }
  • 열거형 상수들은 컴파일 시 static final 상수로 자동 변환됩니다.
  • 위 예제에서 Direction.EAST, Direction.SOUTH 등은 각각 고유한 상수입니다.

열거형 사용 예

class Unit {
    int x, y;
    Direction dir; // 열거형 타입의 인스턴스 변수 선언

    void init() {
        dir = Direction.EAST;
    }
}
  • 열거형 변수는 선언 후 열거형이름.상수 형태로 초기화합니다.

열거형 비교

if (dir == Direction.EAST) { ... }
  • 열거형은 객체지만 == 비교 가능 (같은 인스턴스를 참조하기 때문)
  • .equals()도 가능하지만 == 사용해도 안전함

❗ 주의

if (dir > Direction.WEST) // ❌ 에러 (비교연산자 사용 불가)
  • 대신 compareTo()를 사용해야 함
 
if (dir.compareTo(Direction.WEST) > 0) { ... }

 

 

열거형의 조상 - java.lang.Enum

모든 열거형은 Enum<T> 클래스를 상속받음

  • 자동으로 메서드 제공됨:
Class<E> getDeclaringClass() 열거형의 클래스 반환
String name() 열거형 상수의 이름 반환
int ordinal() 정의된 순서 반환 (0부터 시작)
T valueOf(Class<T> enumType, String name) 이름으로 상수 얻기

values() 메서드

Direction[] dArr = Direction.values();
for(Direction d : dArr)
    System.out.printf("%s=%d%n", d.name(), d.ordinal());
  • values()는 열거형 상수 전체 배열 반환
  • name()은 상수 이름, ordinal()은 순서 반환

예시 출력:

EAST=0
SOUTH=1
WEST=2
NORTH=3

 

valueOf(String name)

Direction d = Direction.valueOf("WEST");
System.out.println(d); // WEST
System.out.println(Direction.WEST == Direction.valueOf("WEST")); // true
  • 문자열 이름으로 상수를 얻을 수 있음
  • valueOf("WEST") → Direction.WEST와 같은 상수 객체 반환

 

요약

전통 방식 enum 방식
int 상수 직접 정의 enum으로 그룹화된 상수 선언
타입 구분 불가능 서로 다른 enum 타입은 비교 불가
상수 값 중복 가능 ordinal 자동 지정, 값 중복 없음
코드 길고 오류 가능성 있음 코드 짧고 명확, 안전성 높음

 

 

열거형에 멤버 추가하기

 

기본 전제: ordinal()은 사용 지양

  • Enum 클래스에 정의된 ordinal() 메서드는 열거형 상수가 정의된 순서(0부터 시작)를 반환합니다.
  • 하지만 이 값은 내부적인 용도로만 쓰이기 때문에, 의미 있는 값으로 사용하지 않는 것이 좋다.
    • 예: Direction.EAST.ordinal() → 0, Direction.WEST.ordinal() → 2

 

의미 있는 값을 넣고 싶을 때는?

ordinal() 대신 우리가 원하는 정수값을 직접 넣고 싶다면, 열거형 상수 옆에 값을 지정하고, 그 값을 저장할 멤버 필드와 생성자를 추가하면 됩니다.

 

예시

enum Direction {
    EAST(1), SOUTH(5), WEST(-1), NORTH(10); // 상수 정의와 동시에 값 지정

    private final int value; // 값 저장용 필드

    Direction(int value) {   // 생성자 정의
        this.value = value;
    }

    public int getValue() {  // 외부에서 값 가져오는 메서드
        return value;
    }
}

포인트 설명:

  • EAST(1) 등은 Direction 생성자 호출과 같음 → Direction(1) 호출
  • value는 각 상수가 가지는 실제 의미 있는 값
  • 외부에서 direction.getValue()로 접근 가능
  • value는 final로 선언했기 때문에 상수처럼 한 번만 초기화됨

 

⚠️ 주의 사항

🔸 열거형 생성자는 외부에서 호출할 수 없다

Direction d = new Direction(1); // ❌ 컴파일 에러
  • 이유: enum 생성자는 private이기 때문
  • 직접 인스턴스를 생성할 수 없고, 선언된 상수만 사용 가능

enum Direction { ... Direction(int value) { ... } }
→ 생성자는 명시적으로 private을 붙이지 않아도 컴파일러가 자동으로 private로 처리함

 

마지막 상수 뒤에 ; 붙이기

  • enum에 필드나 메서드를 추가하려면, 상수 목록의 끝에 반드시 세미콜론(;)을 붙여야 함
EAST(1), SOUTH(5), WEST(-1), NORTH(10); // 세미콜론 필수!

 

 

요약

ordinal() 상수 정의 순서를 의미. 사용 지양
getValue() 우리가 직접 지정한 의미 있는 정수 반환
생성자 열거형 내부에서만 사용 가능 (private)
외부에서 new 사용 불가능. 컴파일 에러
상수 뒤 ; 필드나 메서드 정의 시 반드시 필요

'Java' 카테고리의 다른 글

표준 애너테이션  (0) 2025.06.26
애너테이션  (0) 2025.06.26
와일드 카드, 지네릭 메서드  (0) 2025.06.26
지네릭스 제약네릭스 제약  (0) 2025.06.25
Iterator, HashMap과 지네릭스  (0) 2025.06.25