Enum 클래스

de_sj_awa·2021년 5월 2일
0
post-custom-banner

Enum 클래스

final로 String과 같은 문자열이나 숫자들을 나타내는 기본 자료형의 값을 고정할 수 있다. 이렇게 고정된 값을 "상수"라고 하고, 영어로는 constant라고 한다. 그런데, 어떤 클래스가 상수만으로 만들어져 있을 경우에는 반드시 class로 선언할 필요는 없다. 이럴 때 class라고 선언하는 부분에 enum이라고 선언하면 "이 객체는 상수의 집합이다"라는 것을 명시적으로 나타낸다. enum은 enumeration이라는 "셈, 계산, 열거, 목록, 일람표"라는 영어 단어의 앞부분만 따서 만들어진 예약어이다.

먼저 enum 클래스는 어떻게 보면 타입이지만, 클래스의 일종이다. 그래서 enum 클래스라고 부르면 된다. 한글로 번역해서 "열거형" 클래스라고 불러도 무방하다. 다음의 예를 보자.

package c.enums;

public enum OverTimeValues {
    THREE_HOUR,
    FIVE_HOUR,
    WEEKEND_FOUR_HOUR,
    WEEKEND_EIGHT_HOUR;
}

enum 클래스에 있는 상수들은 지금까지 살펴본 변수들과 다르게 별도로 타입을 지정할 필요도 없고, 값을 지정할 필요도 없다. 그냥 해당 상수들의 이름만 콤마로 구분하여 나열해 주면 된다. enum 클래스에 이와 같이 상수들만 선언하면 가장 마지막에 있는 세미콜론도 필요 없다.

그렇다면 이러한 enum 클래스는 어떻게 사용할까? 가장 효과적으로 enum 클래스를 사용하는 방법은 switch문에서 사용하는 것이다. 다음 예제 코드를 보자.

package c.enums;

public class OverTimeManager {
    public int getOverTimeAmount(OverTimeValues value) {
        int amoutn = 0;
        System.out.println(value);
        switch(value) {
          case THREE_HOUR;
            amount = 18000;
            break;
          case FIVE_HOUR;
            amount = 30000;
            break;
          case WEEKEND_FOUR_HOUR:
            amount = 40000;
            break;
          case WEEKEND_EIGHT_HOUR:
            amount = 60000;
            break;
        }
        return amount;
    }
}    

getOverTimeAmount() 메소드를 보면 OverTimeValues라는 enum 타입을 매개 변수로 받고, 변수명은 value로 지정했다. 야근 수당을 리턴할 amount라는 int 타입을 선언하고 0을 기본값으로 선언하고, 가장 마지막 줄에 그 값을 리턴한다.

메소드의 중간에는 switch문을 사용하였으며, switch 조건으로 value를 지정하였다. switch 내의 case에는 OverTimeValues에 선언한 상수 값들로 분기하도록 했다.

그러면 OverTimeValues라는 enum 타입을 어떻게 getOverTimeAmount() 메소드에 전달할까? 다음 main 메소드를 보자.

public static void main(String[] args) {
    OverTimeManager manager = new OverTimeManager();
    int myAmount = manager.getOverTimeAmount(OverTimeValue.THREE_HOUR);
    System.out.println(myAmount);

밑에서 두 번째 줄을 보면, 별도의 생성자도 필요 없고, 그냥 enum을 넘겨주는 것이 아니라는 것을 알 수 있다. OverTimeValues.THREE_HOUR를 매개 변수로 넘겨 주었다. 가장 쉽게 이해하는 방법은 enum 타입은 "enum 클래스이름.상수 이름"을 지정함으로써 클래스의 객체 생성이 완료된다고 생각하면 된다.

보통은 이와 같이 간단하게 별도의 변수를 생성하지 않고 사용하지만, 이해를 돕기 위해서 다음의

int myAmount = manager.getOverTimeAmount(OverTimeValues.THREE_HOUR);

코드를 풀어서 쓰면 다음과 같이 구현할 수 있다.

OverTimeValues value = OverTimeValues.THREE_HOUR;
int myAmount = manager.getOverTimeAmount(value);

여기서 value라는 변수는 OverTimeValues라는 enum 클래스의 객체라고 생각하면 된다. 하지만, enum 클래스는 생성자를 만들 수 있지만, 생성자를 통하여 객체를 생성할 수는 없다.

enum 상수 값을 지정하는 것도 가능하다. 단, 값을 동적으로 할당하는 것은 불가능하다. 예제는 다음과 같다.

package c.enums;

public enum OverTimeValues2 {
    THREE_HOUR(18000);
    FIVE_HOUR(30000);
    WEEKEND_FOUR_HOUR(40000);
    WEEKEND_EIGHT_HOUR(60000);
    private final int amount;
    OverTimeValue2(int amout) {
        this.amount = amount;
    }
    public int getAmount() {
        return amount;
    }
}

상수 아래에는 amount라는 변수는 final로 선언되어 있다. 이 변수는 그 다음 줄에 있는 OverTimeValues2의 생성자에서 생성자의 선언부를 보면 public이라고 되어 있지 않다. 이렇게 enum 클래스의 생성자는 아무것도 명시하지 않는 package-privateprivate만 접근제어자로 사용할 수 있다. 그런데, public과 protected를 생성자로 사용해서는 안 된다. 다시 말해서, 각 상수를 enum 클래스 내에서 선언할 때에만 이 생성자를 사용할 수 있다. 그렇다면, 앞의 예제에서 사용한 enum 클래스는 생성자도 없는데 어떻게 이상없이 작동했을까? enum 클래스는 일반 클래스와 마찬가지로, 컴파일할 때 생성자를 자동으로 만들어준다.

그 다음에 있는 getAmount()라는 메소드는 enum 클래스의 변수로 선언한 amount 값을 리턴하기 위해서 만들었다. 이처럼 enum 클래스에도 보통 클래스와 마찬가지로 메소드를 선언해서 사용할 수 있다.

자바에서는 다중 상속의 허용되지 않지만, 일반 클래스들은 상속에 상속을 거쳐서 여러 부모 클래스를 가질 수 있다. 하지만, enum 클래스는 무조건 java.lang.Enum이라는 클래스의 상속을 받는다. 즉, extends java.lang.Enum이라는 문장을 enum 클래스를 선언할 때 사용하지는 않지만, 컴파일러가 알아서 이 문장을 추가해서 컴파일한다. 그래서 마음대로 enum을 선언하여 마음대로 extends하면 안 돈다. 게다가, 누가 만들어놓은 enum을 extends를 이용하여 선언할 수는 없다.

Enum 클래스의 생성자는 다음과 같다.

접근 제어자 메소드 설명
protected Enum(String name, int oridinal) 컴파일러에서 자동으로 호출되도록 해놓은 생성자다. 하지만, 개발자가 이 생성자를 호출할 수는 없다.

여기서 name은 enum 상수의 이름이다. ordinal은 enum의 순서이며, 상수가 선언된 순서대로 0부터 증가한다.

Enum 클래스에서 사용하는 메소드는 다음과 같다.

메소드 내용
compareTo(E e) 매개 변수로 enum 타입과의 순서(ordinal) 차이를 리턴한다.
getDeclaringClass() 클래스 타입의 enum을 리턴한다.
name() 상수의 이름을 리턴한다.
ordinal() 상수의 순서를 리턴한다.
valueOf(Class enumType, String name) static 메소드다. 첫 번째 매개 변수로는 클래스 타입의 enum을, 두 번째 매개변수로는 상수의 이름을 넘겨주면 된다.

이 중에서 그나마 많이 사용되는 메소드가 compareTo() 메소드다. Enum 생성자에서 설명했지만, Enum이 선언된 순서대로 각 상수들의 순서가 정해진다. compareTo() 메소드는 이 순서가 같은지, 다른지를 비교하는 데 사용된다. 만약 같은 상수라면 0을, 그렇지 않고 다르면 순서의 차이를 출력한다. 순서의 차이는 메소드의 매개 변수로 넘기는 상수 기준으로 앞에 있으면 음수(-)를, 뒤에 있으면 양수(+)를 리턴한다.

enum 클래스에는 API 문서에는 없는 특수한 메소드가 하나 잇다. 바로 values()라는 메소드이다. 이 메소드를 호출하면 enum 클래스에 선언되어 있는 모든 상수를 배열로 리턴한다. 어떤 상수가 어떤 순서로 선언되었는지 확인하기가 어려운 경우에 이 메소드를 사용하면 된다.

참고

  • 자바의 신
profile
이것저것 관심많은 개발자.
post-custom-banner

0개의 댓글