[Java][enums] 열거형(enums)

2022. 8. 3. 16:52JAVA/Language

2.1 열거형이란 무엇인가?

열거형은 서로 관련된 상수를 편리하게 선언하기 위해서 자바에서 지원하는 타입입니다.

//before
class Card{
    static final int CLOVER = 0;
    static final int HEART = 1;
    static final int DIAMOND = 2;
    static final int SPADE = 3;
    
    static final int TWO = 0;
    static final int THREE = 1;
    static final int FOUR = 2;
    
    final int kind;
    find int num;
}

//after
class Card{
    enum Kind {CLOVER, HEAR, DIAMOND, SPADE} // 열거형 Kind를 정의
    enum Value {TWO, THREE, FOUR}
    
    final Kind kind;
    final Value value;
}

 

2.2 열거형의 정의와 사용

enum 열거형이름 {상수명1, 상수명2, ...}

enum Direction {EAST, SOUTH, WEST, NORTH}

Direction dir = Direction.EAST;

열거형의 특징

  • 열거형 상수간의 비교에 "=="를 사용할 수 있습니다.
  • ">", "<"와 같은 비교연산자를 사용할 수 없고 compareTo()를 사용할 수 있습니다.

 

Enum 클래스에 정의된 메서드

메서드 설명
Class<E> getDeclaringClass() 열거형의 Class 객체를 반환
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환(0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환

 

Enum 클래스의 예제

    @Test
    public void compareDirectionTest(){
        //given
        Direction d1 = Direction.EAST;
        Direction d2 = Direction.valueOf("WEST");
        Direction d3 = Enum.valueOf(Direction.class, "EAST");

        //when
        boolean actual1 = d1 == d2;
        boolean actual2 = d1 == d3;
        boolean actual3 = d1.equals(d3);
        int actual4 = d1.compareTo(d3);
        int actual5 = d1.compareTo(d2);

        //then
        assertThat(d1).isEqualTo(Direction.EAST);
        assertThat(d2).isEqualTo(Direction.WEST);
        assertThat(d3).isEqualTo(Direction.EAST);

        assertThat(actual1).isFalse();
        assertThat(actual2).isTrue();
        assertThat(actual3).isTrue();
        assertThat(actual4).isEqualTo(0);
        assertThat(actual5).isLessThan(0);
    }

 

2.3 열거형에 멤버 추가하기

Enum 클래스에 정의된 ordinal()이 열거형 상수가 정의된 순서를 반환하지만, 이 값을 열거형 상수의 값으로 사용하지 않는 것이 좋습니다. 왜나하면 열거형 상수 중간에 새로운 상수가 추가되면 의도되지 않는 상수가 될 수 있습니다.

// 초기 열거형 상수
enum Direction { EAST, SOUTH, WEST, NORTH} // ordinal : 0 1 2 3

// 중간에 또다른 상수 추가
enum Direction { EAST, EAST-SOUTH, SOUTH, WEST, NORTH} // ordinal : 0 1 2 3 4

 

열거형 상수에 값을 설정

enum 열거형이름 {상수명1(값1, 값2, ...), 상수명2(값1, 값2, ...), ...}

enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10)}

 

열거형 상수에 값을 설정시 주의점

  • 열거형 상수에 값을 설정할 때 인스턴스 변수와 생성자를 추가해주어야 합니다.
enum Direction{
    EAST(1, ">"), SOUTH(2, "V"), WEST(3, "<"), NORTH(4, "^");

    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;
    }
}

 

 

열거형에 추상 메서드 추가하기

각각의 운송수단 상수에 설정된 값은 운송수단에 대한 기본요금 값입니다. 그리고 요금을 계산시에는 거리*기본요금으로 계산됩니다. 거리에 따라서 요금을 계산하는 방식이 각 운송수단마다 다르기 때문에 fare(int distance) 추상 메서드를 선언하여 열거형 상수가 추상 메서드를 구현하도록 합니다.

enum Transportation {
    BUS(100) {
        @Override
        int fare(int distance) {
            return distance * BASIC_FARE;
        }
    },
    TRAIN(150) {
        @Override
        int fare(int distance) {
            return distance * BASIC_FARE;
        }
    },
    SHIP(100) {
        @Override
        int fare(int distance) {
            return distance * BASIC_FARE;
        }
    },
    AIRPLANE(300) {
        @Override
        int fare(int distance) {
            return distance * BASIC_FARE;
        }
    };

    protected final int BASIC_FARE; // protected로 해야 각 상수에서 접근이 가능함

    Transportation(int BASIC_FARE) {
        this.BASIC_FARE = BASIC_FARE;
    }

    public int getBASIC_FARE() {
        return BASIC_FARE;
    }

    abstract int fare(int distance); // 거리에 따른 요금 계산

}
    @Test
    public void checkTransportationFareMethodTest(){
        //given
        Transportation bus = Transportation.BUS;
        Transportation train = Transportation.TRAIN;
        Transportation ship = Transportation.SHIP;
        Transportation airplane = Transportation.AIRPLANE;

        //when
        int actualPrice1 = bus.fare(100);
        int actualPrice2 = train.fare(100);
        int actualPrice3 = ship.fare(100);
        int actualPrice4 = airplane.fare(100);

        //then
        assertThat(actualPrice1).isEqualTo(10000);
        assertThat(actualPrice2).isEqualTo(15000);
        assertThat(actualPrice3).isEqualTo(10000);
        assertThat(actualPrice4).isEqualTo(30000);
    }

 

References

source code : https://github.com/yonghwankim-dev/java_study/tree/main/ch12/_02_enums
[도서] Java의 정석, 남궁 성 지음