본문 바로가기

JAVA

JAVA의 정석 - 열거형(enums)

enums.html

JAVA의 정석

2018-12-16

열거형(enums)

열거형이란

    class Card {
        enum Kind { CLOVER, HEART, DIAMOND, SPACE }
        enum Value { ONE, TOW, THREE, FOUR }

        final Kind kind;
        final Value value;
    }

자바의 열거형은 C언어의 열거형보다 더 향상된 것으로, 타입까지 관리하기 떄문에 보다 논리적인 오류를 줄일 수 있다.
그리고 더 중요한 것은 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일해야 한다는 것이다. 하지만 열거형 상수를 사용하면, 기존의 소스를 다시 컴파일 하지 않아도 된다.
열거형 상수간의 비교에는 '=='를 사용할 수 있다. 그만큼 빠른 성능을 제공한다. 단 비교연산자는 사용 불가하다.
compartTo()는 사용 가능하다.
메서드 설명
Class getDeclaringClass() 열거형의 Class 객체를 반환한다.
String name() 열거형 상수의 이름을 문자열로 반환한다.
int ordinal() 열거형 상수가 정의된 순서를 반환한다.(0부터 시작)
T valueOf(Class enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다.



열거형에 멤버 추가하기

    Enum클래스에 정의된 ordinal()이 열거형 상수가 정의도니 순서를 반환하지만, 이 값을 열거형 상수의 값으로 사용하지 않는 것이 좋다. 이 값은 내부적인 용도로만 사용되기 때문이다. 열거형 상수의 값이 불연속적인 경우에는 열거형 상수의 이름 옆에 원하는 값을 괄호()와 함께 적어주면 된다.

    enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }
    지정된 값을 저장할 수 있는 인스턴스 변수와 새엇ㅇ자를 새로 추가해줘야 하는데, 이 때 먼저 열거형 상수를 모두 정의한 다음에 다른 멤버들을 추가해야한다.
    enum Direction {
        EAST(1), SOUTH(5), WEST(-1), NORTH(10);

        private final int value;
        Direction(int value) { this.value = value; }

        public int getValue() { return value; }
    }

    필요한 경우 여러 값을 지정할 수 있다.

    enum Direction {
        EAST(1, ">"), SOUTH(5, "<""), WEST(-1, "^");

        private final int value;
        Direction(int value) { this.value = value; }

        public int getValue() { return value; }
    }

열거형의 생성자는 묵시적으로 private이므로 외부에서 생성 불가능하다.



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

    열거형에 정의된 추상 메서드를 추가하여 구현할 수 있다.

    enum Transportation {
        BUS(100) {
            int fare(int distance) { return distance * BASIC_FARE; }
        }

        abstarct int fare(int distance);
        protected final int BASEC_FARE;

        Transportation(int basicFare) {
            BASIC_FARE = basicFare;
        }

        public int getBasicFare() { return BASIC_FARE; }
    }



열거형의 이해

열거형이 내부적으로 구현된 형태를 보여준다.


    class Direction {
        static final Direction EAST = new Direction("EAST");
        static final Direction SOUTH = new Direction("SOUTH");
        static final Direction WEST = new Direction("WEST");
        static final Direction NORTH = new Direction("NORTH");

        private String name;

        private Direction(String name) {
            this.name = name;
        }
    }

    Direction클래스의 static상수 EAST, 등드의 값은 객체의 주소이고, 이 값은 바뀌지 안흔 값이므로 '=='로 비교가 가능한 것이다.

    abstract class MyEnum<T extends MyEnum<T>> implements Comparable<T> {
        static int id = 0;

        int ordinal;
        String name = "";

        public int ordinal() { return ordinal; }

        MyEnum(String name) {
            this.name = name;
            ordinal = id++;
        }

        public int compareTo(T t) {
            return ordinal - t.ordinal();
        }
    }

    만일 클래스를 MyEnum<T>와 같이 선언하였따면, compareTo()를 위와 같이 간단히 작성할 수 없었을 것이다. 타입 T에 ordinal()이 정이되어 있는지 확인할 수 없기 때문이다. 이것은 MyEnum<T>의 자손이어야 한다는 의미로 확실히 알려주기 위해 ordinal을 가지고 있는 MyEnum<T>를 상속 받는다고 정의해 둔 것이다.

'JAVA' 카테고리의 다른 글

[JAVA] Reflection 을 이용하여 Method 호출하기  (0) 2020.01.08
[Java] POJO 와 Beans 의 차이점  (0) 2019.08.24
JAVA의 정석 - Thread  (0) 2019.01.13
JAVA의 정석 - Generics  (0) 2019.01.13