[Java] Enum 정의와 활용

Jiwoo Kim·2021년 7월 8일
0

머리에 자바 넣기

목록 보기
3/4
post-thumbnail

Enum

Enum이란 Enumeration의 앞 글자를 딴 약어로, 직역하면 열거라는 의미다. 서로 관련있는 상수들을 모아서 대표 이름으로 클래스를 정의하고 활용하는 데에 사용된다.


내부 구현


가장 기본적이고 간단한 Enum 타입을 통해 내부 기본적인 구현 형태를 알아 보자. Direction 이라는 Enum 클래스가 아래와 같이 정의되어 있다고 하자.

enum Direction {  EAST, WEST, SOUTH, NORTH  }

동서남북을 값으로 갖는 이 클래스는, 내부적으로 아래와 같이 구현된다.

enum Direction {

    static final Direction EAST = new Direction("EAST");
    static final Direction WEST = new Direction("WEST");
    static final Direction SOUTH = new Direction("SOUTH");
    static final Direction NORTH = new Direction("NORTH");
  
    private String name;
  
    private Direction(String name)  { this.name = name; }
}

Default 필드로 name이 생성되고, Default 생성자로는 name을 할당하는 생성자가 구현된다.

Default 생성자의 접근제어자는 묵시적으로 private이며, public일 수 없다. 외부에서 Enum 상수에 접근하려면 생성자가 아니라, Direction.EAST와 같은 형식으로 접근해야 한다.


API


Enum 클래스는 기본적으로 몇 가지 편의 메서드를 제공한다.

Instance Method

  • int ordinal()

Enum 클래스 안에서의 상수의 Index를 반환한다. Index는 선언된 순서대로 0부터 시작한다.

  • String name(), String toString()

Enum 클래스 안에서의 상수의 이름을 반환한다.

Static Method

  • Enum<T>[] values()

Enum 클래스에 있는 모든 상수값을 배열로 반환한다. String[]이 아니라, Enum 클래스 타입의 객체로 반환하는 것이다.

  • Enum<T> valueOf(String name)

Enum 클래스 안에서 인자로 들어온 name과 같은 이름의 상수가 있으면 그 상수 객체를 반환한다.


활용


상속

Enum 클래스는 java.lang.Enum<E> 클래스를 기본적으로 상속하기 때문에, 다른 클래스를 추가로 상속할 수 없다.


비교

두 Enum 객체의 값을 비교하여 Index 비교 결과를 반환하는 메서드가 내부적으로 구현되어 있다.

  • int compareTo(E o)
  • boolean equals(Object other)

두 메서드 모두 기본적으로 Enum 클래스 안에서 선언된 순서를 비교하여 결과를 산출한다.

💡 같은 Enum Type 객체들 간 비교는 == 연산자로도 가능하다. equals()를 사용해도 내부적으로 == 연산자를 호출하기 때문에, ==를 사용해서 비교하는 것이 더 효율적이다. 하지만 >, <와 같은 연산자 비교는 불가능하다.


Additional Field

Enum 상수들은 name 말고도 다른 값들을 필드로 가질 수 있다.

enum Direction {

    EAST(1, ">"),
    SOUTH(5, "V"),
    WEST(-1, "<"),
    NORTH(10, "^");
    
    private final int value;
    private final String symbol;
    
    Direction(int value, String symbol) {
    	this.value = value;
    	this.symbol = symbol;
    }
    
    public int getValue() { return value; }
    public String getSymbol() { return symbol; }
}

다형성

Enum 클래스에 추상 메서드를 선언하고, 상수마다 추상 메서드를 구현하여 다형성을 구현할 수 있다.

Abstract Method

Enum 클래스 안에 추상 메서드를 선언하면, 각 상수들은 그 메서드를 오버라이딩해야 한다. 이를 통해 같은 기능을 상수마다 다르게 구현할 수 있다.

enum Transportation {

    BUS(100) {  int fare(int distance) {  return distance * basicFare; }},
    TRAIN(150) {  int fare(int distance) {  return distance * basicFare; }},
    AIRPLANE(300) {  int fare(int distance) {  return distance * basicFare; }};

    abstract int fare(int distance);

    protected final int basicFare;

    Transportation(int basicFare) { basicFare = basicFARE; }

    public int getBasicFare() { return basicFare; }
}

근데 body 자체를 다 적어줘야 하다보니 코드가 굉장히 지저분해진다. 그럴 때 사용할 수 있는 것이 아래 Lambda다.

Lambda

아래는 Functional Interface와 Lambda를 활용해 Enum 클래스에서 기능을 구현한 것이다.

import java.util.function.DoubleBinaryOperator;

enum Operator {

    PLUS((a, b) -> a + b),
    MINUS((a, b) -> (a - b)),
    MULTIPLY((a, b) -> (a * b)),
    DIVIDE((a, b) -> (a / b));

    private final DoubleBinaryOperator doubleBinaryOperator;

    Operator(DoubleBinaryOperator doubleBinaryOperator) {
        this.doubleBinaryOperator = doubleBinaryOperator;
    }

    public Double calculate(double a, double b) {
        return this.doubleBinaryOperator.applyAsDouble(a, b);
    }
}

Operator 클래스는 외부에서 아래와 같이 사용할 수 있겠다.

Operator.PLUS.calculate(1, 2);		// 3.0
Operator.MINUs.calculate(1, 2);		// -1.0
Operator.MULTIPLY.calculate(1, 2);	// 2.0
Operator.DIVIDE.calculate(1, 2);	// 0.5

기능 구현

Enum 클래스 내부에 상수들과 연관 있는 기능들을 구현하여 효율적으로 관리할 수 있다.

enum Statistic {

    THREE(3, 5000),
    FOUR(4, 50_000),
    FIVE(5, 1_500_000),
    BONUS(5, 3_000_000),
    SIX(6, 2_000_000_000);

    private final int matchingNumbers;
    private final int prize;

    Statistic(int matchingNumbers, int prize) {
        this.matchingNumbers = matchingNumbers;
        this.prize = prize;
    }

    public static Statistic getRank(int numberOfMatch) {
        return Arrays.stream(values())
                .filter(statistic -> statistic.matchingNumbers == numberOfMatch)
                .findFirst()
                .orElseThrow();
    }
}


참고

Java 11 공식 API 문서
자바 Enum 기본 및 활용

0개의 댓글