본문 바로가기
카테고리 없음

[JAVA] enum을 잘 활용하기 위한 기본 지식.

by 손너잘 2021. 4. 22.

자바에서는 enum이라는 열거형 자료형을 표현하기 위한 강력한 도구를 제공해준다.

하지만 enum은 매우 강력한 도구임에도 불구하고, 절차지향 프로그래밍을 해온 사람들에게는 약간의 혼란을 야기한다.

 

자바의 enum은 c언어의 그것과 무엇이 다를까?

 

보통 프로그래밍을 처음 배울때 c언어로 시작할 것이다.(요즘은 파이썬으로 많이 하는 것 같지만..) 그리고 열거형 자료형을 배울 떄 아래와 같은 코드를 많이 봐왔을 것 이다.

enum DayOfWeek {
    Sunday = 0,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

아주 눈에 익은 코드다. 이렇게 정의하면 우리는 Sunday, Monday와 같이 특정 값을 나타내는 변수를 간편히 가져와 사용할 수 있다.

그럼 이번에는 자바의 enum 사용법을 보자.

public enum Week {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
}

 

아주 잘 정의된 enum이다. 사용법 또한 C언어와 비슷하다. 그러면, 그냥 그렇게 사용하면 되지 무엇이 다른다는걸까?

 

먼저 가장 큰 차이점은, C언어의 enum은 자료구조이고, java의 enum은 클래스이다.

따라서 euum은 자바의 객체가 가질 수 있는 여러 장점들을 그대로 끌고갈 수 있다. 그에 반해 c언어의 enum은 단지 정수형 타입 이상 이하도 아니다.

 

이런 특성으로 인해서 서로 다른 타입의 enum을 비교했을때의 문제점 또한 방지할 수 있다.

이게 무슨말인고 하니..

enum WEEK{
    SUN,
    MON
}

enum FRUIT{
    APPLE,
    ORANGE
}

만일 c에 위와같은 enum이 정의돼 있다면, Week.Sun 과 FRUIT.APPLE 은 단순히 1이라는 정수을 나타내기 때문에 WEEK.SUN == FRUIT.APPLE 이 true로 표현된다. 하지만 java의 경우 enum이 클래스로 표현되기 때문에 애초에 둘을 비교하려면 type cast에러를 볼 수 있을것이다.

 

enum은 일종의 객체 집합이다. 따라서 enum의 각 요소가 객체로 취급될 수 있다. 즉, 위 예시에서 SUNDAY, MONDAY... 가 모두 객체로서 취급된다는 것 이다.

 

이렇게 글로만 봐서는 이해가 잘 안될것이다. 그렇다면 위 enum 소스를 한번 자바 코드로 풀어서 써보겠다.

public class Week {
    public static Week SUNDAY = new Week();
    public static Week MONDAY = new Week();
    public static Week TUESDAY = new Week();
    public static Week WEDNESDAY = new Week();
    public static Week THURSDAY = new Week();
    public static Week FRIDAY = new Week();
    public static Week SATURDAY = new Week();
}

그렇다. enum의 실체는 위와 같이 생겼다. 이렇게보니 enum을 어떻게 다루어야 할지 보이는가?

Week 클래스에 정적 메소드, 혹은 비정적 메서드를 넣을수 도 있고, 생성자도 만들 수 있다. 한번 해보자.

 

public class Week {
    public static Week SUNDAY = new Week("일");
    public static Week MONDAY = new Week("월");
    public static Week TUESDAY = new Week("화");
    public static Week WEDNESDAY = new Week("수");
    public static Week THURSDAY = new Week("목");
    public static Week FRIDAY = new Week("금");
    public static Week SATURDAY = new Week("토");

    private final String name ;

    Week(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static Week findByName(String name) {
        Arrays.stream(values())
                .filter(w -> w.getName().equals(name))
                .findAny()
                .orElseThrow(IllegalArgumentException::new);
    }

    private static Week[] values() {
        return new Week[]{
                SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
        };
    }

}

위 소스는 오류없이 잘 작동한다. 그리고 필자는 이렇게 말했다. 위 소스가 enum을 직접 구현한 형태라고. 그렇다는건 위와 같은 형태로 enum을 사용할 수 있다는 것을 의미한다.

 

public enum Week {
    SUNDAY("일"),
    MONDAY("월"),
    TUESDAY("화"),
    WEDNESDAY("수"),
    THURSDAY("목"),
    FRIDAY("금"),
    SATURDAY("토");

    private final String name ;

    Week(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static Week findByName(String name) {
        Arrays.stream(values())
                .filter(w -> w.getName().equals(name))
                .findAny()
                .orElseThrow(IllegalArgumentException::new);
    }
}

 

위 class 로직과 enum 로직의 차이점을 살펴보면 크게 달라진 점은 없다. 다면 선언 방식이 좀 달라졌고, values() 메소드를 enum에서 기본으로 제공한다는게 좀 다를 뿐.

 

이를 통해서 우리는 왜 enum끼리는 == 연산자를 사용해도 되는지 또한 이해할 수 있게 되었다. class소스를 보면 각 원소는 정적으로 생성되고 계속해서 돌려사용된다. 따라서 이 객체들의 주솟값을 변경되지 않고, == 연산자를 사용해도 올바른 비교가 가능해진다.

 

 

이번 글을 통해 우리는 enum이 단순한 데이터 덩어리가 아니라, 하나하나가 객체라는 사실을 알 수 있었다.

그리고 그 특성을 이용해서 여러 로직을 넣을 수 있다는 것을 확인했다.

 

이런 enum의 특성을 이해하고 있다면, 앞으로 enum을 사용하는데 여러가지 인사이트를 떠올릴 수 있을것이라 생각한다.

댓글