일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입을 열거 타입이라고한다. 이런 상수들을 intString으로 열거하게 된다면 단점이 있다.

  • 타입 안전을 보장할 방법이 없고 표현력이 떨어진다. 즉 전혀 관계 없는 타입들의 연산을 하더라도 컴파일러는 경고를 하지않는다.

예시:

public static final int APPLE_FUJI = 0; 
public static final int APPLE_PIPPIN = 1; 
public static final int APPLE_GRANNY_SMITH = 2;
public static final int ORANGE_NAVEL = 0; 
public static final int ORANGE_TEMPLE = 1; 
public static final int ORANGE_BLOOD = 2;

int i = (APPLE_FUJI - ORANGE_TEMPLE) / APPLE_PIPPIN;
  • namespace를 지원하지 않기 때문에 접두사를 쓰면서 이름이 길어진다.

  • 정수 열거의 경우 출력하게 되면 숫자로만 보여서 도움이되지 않고, 문자열의 경우는 문자열 값을 하드코딩할 수도 있게되며, 이 때 오타가 발생해도 찾기가 쉽지않다.

enum을 사용하면 상수 하나당 자신의 인스턴스를 하나씩 만들어 public static final 필드로 공개한다. 따라 서 인스턴스를 딱 하나만 존재하는 것이 보장된다. 그리고 위의 문제들을 모두 해결할 수 있다.

Enum의 장점

  • 열거 타입 상수 각각을 특정 데이터와 연결 지을 수 있다. 따라서 연관된 상수들을 묶어서 관리할 수 있다.

예시:

public enum Planet { 
    MERCURY(3.302e+23, 2.439e6),
    VENUS (4.869e+24, 6.052e6), 
    EARTH (5.975e+24, 6.378e6), 
    MARS (6.419e+23, 3.393e6), 
    JUPITER(1.899e+27, 7.149e7), 
    SATURN (5.685e+26, 6.027e7), 
    URANUS (8.683e+25, 2.556e7), 
    NEPTUNE(1.024e+26, 2.477e7);

    private final double mass; // 질량(단위: 킬로그램)
    private final double radius; // 반지름(단위: 미터)
    private final double surfaceGravity; // 표면중력(단위: m / s^2)

    // 중력상수(단위: m^3 / kg s^2)
    private static final double G = 6.67300E-11;

    // 생성자
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
        surfaceGravity = G * mass / (radius * radius);
    }

    public double mass() { return mass; }
    public double radius() { return radius; }
    public double surfaceGravity() { return surfaceGravity; }

    public double surfaceWeight(double mass) {
        return mass * surfaceGravity; // F = ma }
    }
}
  • 상수마다 동작이 달라져야 하는 상황도 처리할 수 있다. 즉, 상태와 행위를 한 곳에 표현할 수 있다.

예시:

public enum Operation { 
    PLUS("+") {
        public double apply(double x, double y) { return x + y; } 
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; } 
    },
    TIMES("*") {
        public double apply(double x, double y) { return x * y; } 
    },
    DIVIDE("/") {
        public double apply(double x, double y) { return x / y; } 
    };

    private final String symbol;

    Operation(String symbol) { this.symbol = symbol; }

    @Override public String toString() { return symbol; }
    public abstract double apply(double x, double y); 
}

위의 경우에는 Functional Interface를 이용하여서도 구현할 수 있다.

public enum Operation {
    PLUS((x, y) -> x + y),
    MINUS((x, y) -> x - y),
    TIMES((x, y) -> x * y),
    DIVIDE((x, y) -> x / y);
    
    private BiFunction<Double, Double, Double> operationFuntion;   
}

참고

댓글남기기