본문 바로가기

3.구현/Java or Kotlin

[java] enum 사용하기

들어가기

enum은 잘 사용하지 않은 기능 중에 하나이다. 익숙하지도 않지만, 사용하기 불편하다는 이유도 있기도 하다. 그러나 알아두면, 정말 유용하게 사용할 일이 많다. :)

작성자: http://ospace.tistory.com/,2016.11.11 (ospace114@empal.com)

그냥 상수형 데이터?

그냥 상수형 데이터를 정의해서 사용한다고 하면 다음과 같이 사용할 경우가 대부분이다.

class Week {
    public final static int SUNDAY = 0;
    public final static int MONDAY = 1;
    public final static int TUESDAY = 2;
    // ...
}

// 주말여부
pubic bool isWeekend(int week) {
    if (Week.SUNDAY == week || Week.SATURDAY == week) {
        return true;
    }
        return false;
}

위의 방식도 나쁘지는 않다. 계속 확장할 수도 있다. 그러나 상수값이 변경되는 과정에서 숫자가 같은 값을 사용하는 경우 컴파일 과정에서 에러가 없으므로 그냥 넘어가게 된다.
그렇게되면 추후 예기치 못한 문제가 발생할 경우가 생긴다. 물론 테스트 코드를 완벽하게 모든 경우에 대해 작성했다면, 이런 문제는 발생하지 않을 것이지만, 그러기가 쉽지 않다.

또한 값을 읽기 쉬운 문자열로 변환하여 처리할 경우 일일히 매핑해야한다는 불편한 점도 있다.

enum 사용해보자

enum을 사용하는 간단한 방법을 알아보자. 앞의 예제의 경우를 먼저 살펴보자.

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

public bool isWeekend(Week week) {
    if (Week.SUNDAY == week || Week.SATURDAY == week) {
        true;
    }
    return false;
}

무엇인지는 모르지만, 간결해졌다. ㅡ.ㅡ;;; 그리고 앞에서 사용했던 숫자 상수 부분이 사라졌다.

enum 좀더 활용해보자

이번에는 enum을 좀더 활용하는 방법으로 내부에 메소드를 추가하는 방법이다. 다음은 각 요일별로 문자열 출력하기 위한 부분이다. 만약 앞에 숫자 상수를 사용할 경우 if문이나 switch문을 사용해서 개별적으로 문자열을 반환해야한다.
enum을 이용해서 각 요일별 문자열을 사용할 수 있는 예제이다.

enum Week {
    SUNDAY("일요일"),
    MONDAY("월요일"), 
    //중략
    SATURDAY("토요일");

    final String name;

    // 생성자로 각 enum값 생성시 사용
    Week(String name) {
        this.name = name;
    }

    public static Week getCode(String str) {
        return Arrays.stream(Week.values())
            .filter(it->it.equals(str))
            .findAny()
            .orElse(null);
    }

    public static Week get(String str) {
      for(Week it : Week.values()) {
        if(it.equals(str)) return it;
      }
      return null;
    }

    public boolean equals(String code){
        return this.code.equals(code);
    }
}

// 사용예
System.out.println("요일: " + Week.SUNDAY.name);

name 필드를 getter를 사용하지 않은 이유는 해당 값은 고정된 값이고, 불필요한 코드와 코드량이 증가하기 때문에 property를 사용해서 작성하였다. 이는 자신의 상황에 맞게 수정하면 된다. Week 열거형 안에 사용할 값들을 정의하는데 객체 생성처럼 정의되고 있다. 해당 값은 Week 생성자가 호출되는 값이름은 객체 명이 된다고 보면 이해하기 쉽다.

앞의 getCode()를 사용함에 있어서 for문으로 변경가능하다. get()은 for문을 사용한 예이다. 그냥 참고하면 됩니다. 가독성 측면에서는 아래가 좋아보이네요.

전체 코드

아래는 전체 코드이다. 조금 수정했다.

enum Week {
    SUN("sunday", "일", 0),
    MON("monday", "월", 1),
    TUE("thuesday", "화", 2), 
    WED("wednesday", "수", 3), 
    THU("thursday", "목", 4), 
    FRI("friday", "금", 5), 
    SAT("saturday" "토", 6);

    final String name;
    final String nameKr;
    final int index;

    // 생성자로 각 enum값 생성시 사용
    Week(String name, String nameKr, int index) {
        this.name = name;
        this.nameKr = nameKr;
        this.index = index;
    }

    public static Week getCode(String str) {
        return Arrays.stream(Week.values())
            .filter(it->it.equals(str))
            .findAny()
            .orElse(null);
    }

    public static Week get(String str) {
      for(Week it : Week.values()) {
        if(it.equals(str)) return it;
      }
      return null;
    }

    public static Map<String,String> toMap() {
      Map<String,String> ret = new HashMap<>();
      for(Week it : Week.values()) {
        ret.put(it.value, it.name);
      }
      return ret;
    }

    public boolean equals(String code){
        return this.name.equals(code);
    }

    public boolean equals(int index){
        return this.index == index;
    }

    public String toString() {
      return name;
    }
}

결론

enum은 알고 보면 코드량도 줄일 수 있지만 실수도 줄일 수 있는 일석이조의 효과를 가져다 준다. 물론 이를 사용하기 위해서 공부를 해야한다. ^^; 그리고 if문과 switch문을 없애는 효과는 성능적인 측면에서도 영향을 무시할 수 없다.

참조

[1] Enum Types, https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

History

2024.01.25 문구 매끄럼게 수정 및 전체 코드 추가

반응형