Web/Java

[Java] Enum

  • enum 정의하는 방법
  • enum이 제공하는 메소드 (values()와 valueOf())
  • java.lang.Enum
  • EnumSet

 

Enum

열거형(enum)은 서로 관련된 상수를 편리하게 선언하기 위해 JDK1.5부터 새로 추가되었습니다.

 

 

 

Enum 정의하는 방법

 

enum 열거형이름 다음에 괄호{}안에 상수의 이름을 나열하면 됩니다.

enum 열거형이름 { 상수명1, 상수명2, ... }

 

예시) 동서남북 4방향 열거형

enum Direction { EAST, SOUTH, WEST, NORTH }

 

 

Enum 비교방법

  • '==' 사용 가능
  • '>' '<' 같은 비교연산자 사용 불가능
  • compareTo() 사용 가능
if (dir == Direction.EAST) {
    //가능
} else if (dir > Direction.WEST) {
    // 불가능
} else if (dir.compareTo(Direction.WEST) > 0) {
    // 가능
}
...

 

 

 

java.lang.Enum

모든 열거형의 조상은 Enum 클래스 입니다.

 

Enum클래스에는 다음과 같은 메서드가 정의되어 있습니다.

메서드 설명
Class<E> getDeclaringClass() 열거형의 Class객체를 반환한다.
String name() 열거형 상수의 이름을 문자열로 반환한다.
int ordinal() 열거형 상수가 정의된 순서를 반환한다.(0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다.

 

 

열거형은 상수 하나하나가 자신의 객체입니다.

 

Direction으로 예를들면,

아래와 같은 Direction enum의 상수 EAST, SOUTH, WEST, NORTH는 하나하나가 다 Direction객체입니다.

enum Direction { EAST, SOUTH, WEST, NORTH }

아래 코드로 이해하면 쉽습니다.

class Direction {
    static final Direction EAST = new Direction("EAST");
    static final Direction SOUTH = new Direction("SOUTH");
    static final Direction WEST = new Direction("WEST");
    static final Direction NORTH = new Direction("NORTH");
    
    private String name;

    private Direction(String name) {
        this.name = name;
    }
}

 

 

 

 

실제 Enum을 흉내 내어 MyEnum을 작성해보겠습니다.

abstract class MyEnum<T extends MyEnum<T>> implements Comparable<T> {
    static int id = 0; // 객체에 붙일 번호 (0부터 시작)
    
    int ordinal;
    String name = "";
    
    public int ordinal() {
        return ordinal;
    }

    MyEnum(String name) {
        this.name = name;
        ordinal = id++; // 객체를 생성할 때마다 id의 값을 증가시킨다.
    }

    public int compareTo(T t) {
        return ordinal - t.ordinal();
    }
}

 

객체가 생성될 때마다 번호를 붙여서 인스턴스 변수 ordinal에 저장합니다.

그리고 Comparable 인터페이스를 구현해서 열거형 상수간의 비교가 가능하도록 되어있습니다.

 

 

MyEnum<T extends MyEnum<T>> 인 이유

만약 클래스를 MyEnum<T>와 같이 선언하였다면, compareTo()를 위와 같이 간단히 작성할 수 없었을 것입니다.

왜냐하면 타입 T가 ordinal()이 정의되어 있는지 확인할 수 없기 때문입니다.

    public int compareTo(T t) {
        return ordinal - t.ordinal();
    }

 

그래서 MyEnum<T extends MyEnum<T>>와 같이 선언한 것이며 이것은 타입 T가 MyEnum<T>의 자손이어야 한다는 의미입니다.

 

 

 

 

 

 

실제 Enum 클래스

  • Enum<E extends Enum<E>> 으로 되어있는 것을 볼 수 있다.
  • Comparable<E>도 구현하는 것을 볼 수 있다.

 

 

 

 

 

 

values()

 

values()는 열거형의 모든 상수를 배열에 담아 반환하는 메서드입니다.

이 메서드는 모든 열거형이 가지고있고, 컴파일러가 열거형에 자동으로 추가해줍니다.

 

public class EnumEx1 {
    public static void main(String[] args) {
        Direction[] values = Direction.values();

        for (Direction value : values) {
            System.out.printf("%s = %d\n", value.name(), value.ordinal());
        }
    }
}

 

 

valueOf()

values()와 마찬가지로 컴파일러가 자동으로 추가해주는 메서드입니다.

 

valueOf()는 열거형 상수의 이름으로 문자열 상수에 대한 참조를 얻을 수 있게 해줍니다.

static E values()
static E valueOf(String name)

 

사용예시

Direction d  = Direction.valueOf("WEST");

System.out.println(d); // WEST
System.out.println(Direction.WEST == Direction.valueOf("WEST")); // true

 

 

 

 

EnumSet

 

EnumSet은 Set인터페이스를 기반으로 열거형의 요소들을 가장 쉽고 빠르게 배열처럼 다룰 수 있도록 고안된 구현체 입니다.

 

https://www.geeksforgeeks.org/enumset-class-java/

 

 

EnumSet의 중요한 특징

  • 오직 열거형 상수만을 값으로 가질 수 있습니다.
  • 모든 값은 같은 enum type이어야 합니다.
  • null value 추가를 허용하지 않습니다.
  • NullPointerException을 던지는 것을 허용하지 않습니다.
  • ordinal 값의 순서대로 요소가 저장됩니다.
  • 모든 메서드는 arithmetic 비트연산을 사용하기 때문에 모든 기본 연산의 시간 복잡도가 O(1)입니다.
  • enum과 static타입의 메소드들로 구성되어있어 안정성을 보장합니다.

 

 

 

사용법

 

EnumSet static 메서드 설명
EnumSet.allOf() 매개변수로 받는 열거형에 있는 모든 요소들을 가져온다.
Enum.of() 매개변수로 받는 해당 요소를 찾아서 넣는다.
Enum.complementOf() 매개변수로 받는 요소들만 빼고 넣는다.
EnumSet.range() 매개변수로 받는 두개의 구간안에 해당하는 요소를 넣는다.
EnumSet.noneOf() 매개변수로 받는 열거형을 비운 EnumSet을 반환한다.

 

 

사용예시

package javastudy.ch11;

import java.util.EnumSet;

enum Color {
    RED, YELLOW, GREEN, BLUE, BLACK, WHITE
}
public class EnumDemo {
    public static void main(String[] args) {
        EnumSet<Color> set1, set2, set3, set4, set4_1, set5;

        set1 = EnumSet.allOf(Color.class);
        set2 = EnumSet.of(Color.RED, Color.GREEN, Color.BLUE);
        set3 = EnumSet.complementOf(set2);
        set4 = EnumSet.range(Color.YELLOW, Color.BLACK);
        set5 = EnumSet.noneOf(Color.class);

        set5.add(Color.BLACK);
        set5.add(Color.BLUE);
        set5.remove(Color.BLACK);

        System.out.println("set1 = " + set1);
        System.out.println("set2 = " + set2);
        System.out.println("set3 = " + set3);
        System.out.println("set4 = " + set4);
        try {
            set4_1 = EnumSet.range(Color.BLACK, Color.YELLOW);
            System.out.println("set4_1 = " + set4_1);
        } catch (IllegalArgumentException e) {
            System.out.println("set4_1은 오류가 발생합니다 : " + e.getMessage());
        }
        System.out.println("set5 = " + set5);
    }
}

 

 

 

Enum 사용 참고 블로그

https://honbabzone.com/java/java-enum/

 

Java Enum이란

Emum이라는 열거타입과 내부 열거상수를 이해하고 적절한 사용 방법을 알아보겠습니다.

honbabzone.com

 

'Web > Java' 카테고리의 다른 글

[Java] 제네릭  (1) 2021.08.30
[Java] I/O  (2) 2021.08.24
[Java] 애노테이션  (1) 2021.08.11
[Java] 멀티쓰레드 프로그래밍  (1) 2021.08.06
[Java] 예외  (2) 2021.08.02