Java/Java

Java - enum

Dlise 2023. 9. 22. 12:33

Java의 enum을 알면 효율적인 프로그래밍이 가능해 보여 이에 대해 알아보고자 한다.

 

열거형 선언

JDK 1.5부터 사용 가능한 기능이다.

상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 유용하다.

 

정의는 아래와 같이 한다. 끝에 세미콜론(;)이 없는 것에 주의해야 한다.

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

 

Enum 클래스

enum에 대해 자세히 알아보기 전에 모든 열거형의 조상인 Enum 클래스를 먼저 알아보자.

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Enum.html

 

Enum (Java SE 11 & JDK 11 )

 

docs.oracle.com

Enum는 Serializable, Comparable 인터페이스를 구현한  클래스이다.

 

정의된 메서드는 아래와 같다.

name() 열거형 상수의 이름을 문자열로 반환
valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환
getDeclaringClass() 열거형의 Class객체를 반환
equals(Object other) 지정된 개체가 열거 상수와 같으면  true 반환
compareTo(E o) 열거형을 지정된 개체와 비교 후 양수, 0, 음수 반환 
같은 열거형의 다른 열거형 상수와만 비교 가능
ordinal() 열거 상수 반환

ordinal()는 열거형 상수가 정의된 순서를 0부터 정수로 반환한다.

 

이를 활용한 코드와 출력 결과이다.

enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}

public class EnumPractice {

    public static void main(String[] args) {
        Week week = Week.WEN;
        
        System.out.println("name(): " + week.name());
        System.out.println("valueOf(): " + Week.valueOf("WEN"));
        System.out.println("valueOf(): " + Enum.valueOf(Week.class, "WEN"));
        System.out.println("valueOf(): " + Enum.valueOf(week.getDeclaringClass(), "WEN"));
        System.out.println("getDeclaringClass(): " + week.getDeclaringClass() + "\n");

        System.out.println("equals(): " + week.equals(Week.WEN));
        System.out.println("compareTo(): " + week.compareTo(Week.MON) + "\n");

        System.out.println("ordinal(): " + week.ordinal());
    }
}

크게 어려운 부분은 없다.

 

 

추가로 문서에는 없지만 모든 열거형에 컴파일러가 자동으로 추가해 주는 메서드가 있다.

values() 열거형의 모든 상수를 배열에 담아 반환
valueOf(String name) 열거형 상수 이름으로 문자열 상수에 대한 참조를 얻음
enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}
public class EnumPractice {
    public static void main(String[] args) {
        Week[] week = Week.values();
        
        for(Week w : week) {
            System.out.println(w);
        }
        
        System.out.println("valueOf(String s): " + Week.valueOf("WEN"));
        System.out.println("valueOf(String s)의 Class: " + Week.valueOf("WEN").getClass());
    }
}

특히 values()는 활용성이 높다고 생각한다.

 

열거형 활용

메서드를 알았으니 이제 여러 활용법을 알아보자.

 

기본

가장 기본적인 활용은 아래와 같이 바로 사용하거나 열거형에 맞는 변수를 선언하고 사용하는 것이다.

enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}
enum Direction {EAST, WEST, SOUTH, NORTH}

public class EnumPractice {
    public static void main(String[] args) {
    
	System.out.println(Week.FRI); //바로 사용
        
        Direction dir = Direction.EAST; 
        System.out.println(dir); //변수 선언 후 사용

    }
}

 

switch문

열거형은 switch문에도 활용할 수 있다.

이때 switch문의 조건식엔 '열거형.상수'가 아니라 '상수'만 적어야 한다는 점이다.

'열거형.상수'를 입력하면 컴파일 에러가 발생한다. 

enum Direction {EAST, WEST, SOUTH, NORTH}

public class EnumPractice {
    public static void main(String[] args) {
        Direction dir = Direction.EAST;

        switch (dir) {
            case EAST:
                System.out.println("EAST");
                break;
            case WEST:
                System.out.println("WEST");
                break;
            case SOUTH:
                System.out.println("SOUTH");
                break;
            case NORTH:
                System.out.println("NORTH");
                break;
        }
    }
}

 

상수

ordinal()을 활용하면 각 열거형 상수에 대해 정수를 반환한다.

하지만 이 값은 직접 선언한 것이 아니기 때문에 활용을 권장하지 않는다.

 

이를 대신해 괄호를 이용해 각 열거형 상수에 대해 추가적인 정보를 저장할 수 있다.

 

아래 코드는 각 요일마다 무작위로 상수를 담은 것이다.

이렇게 활용할 때 주의할 점은

1. 세미콜론(;)을 붙여야 한다.

2. 인스턴스 변수와 생성자를 구현해야 한다. 

이다.

enum Week {
    MON(1), TUE(3), WEN(4), THU(6), FRI(7), SAT(8), SUN(10); //세미콜론

    private final int value; //인스턴스 변수

    Week(int value) { //생성자
        this.value = value; 
    }

    public int getValue() {
        return value;
    }
}

public class EnumPractice {
    public static void main(String[] args) {
        Week week = Week.WEN;
        System.out.println(week.getValue());
    }
}

출력 결과는 "4"이다.

 

생성자를 구현했으면 아래와 같이 활용할 수 있지 않을까 생각이 드는데 컴파일 에러가 발생한다.

그 이유는 enum의 생성자는 default 제어자가 private이기 때문이다.

 

 

괄호 안에 여러 개의 변수를 활용할 수도 있다.

enum Week {
    MON(1, "월요일"), TUE(3, "화요일"), WEN(4, "수요일"), 
    THU(6, "목요일"), FRI(7, "금요일"), SAT(8, "토요일"), SUN(10, "일요일");

    private final int value;
    private final String korean;
    Week(int value, String korean) { 
        this.value = value; 
        this.korean = korean;
    }

    public int getValue() {
        return value;
    }

    public String getKorean() {
        return korean;
    }

    public String toString() {
        return korean + " " + value;
    }
}

public class EnumPractice {
    public static void main(String[] args) {
        Week week = Week.WEN;
        System.out.println(week.getValue());
        System.out.println(week.getKorean());
        System.out.println(week.toString());
    }
}

활용성이 매우 높다.

 

추상 메서드

열거형 클래스에 추상 메서드를 활용할 수도 있다.

열거형 상수의 경우마다 다른 메서드를 구현해야 하는 경우가 있을 수 있기 때문이다.

enum Week {
    MON(1, "월요일") {String schedule() {return basic + "독서하기";}}, 
    TUE(3, "화요일") {String schedule() {return basic + "산책하기";}}, 
    WEN(4, "수요일") {String schedule() {return basic + "게임하기";}}, 
    THU(6, "목요일") {String schedule() {return basic + "공부하기";}}, 
    FRI(7, "금요일") {String schedule() {return basic + "다시자기";}}, 
    SAT(8, "토요일") {String schedule() {return basic + "요리하기";}}, 
    SUN(10, "일요일") {String schedule() {return basic + "명상하기";}};

    abstract String schedule();
    protected final String basic = "일어나서 ";

    private final int value;
    private final String korean;
    
    Week(int value, String korean) { 
        this.value = value; 
        this.korean = korean;
    }
    
    public int getValue() {
        return value;
    }

    public String getKorean() {
        return korean;
    }

    public String toString() {
        return korean + " " + value;
    }
}

public class EnumPractice {
    public static void main(String[] args) {
        for(Week week : Week.values())
            System.out.println(week.schedule());
    }
}