Hyunebee

Enum 본문

Java/Java의 정석

Enum

Hyunebee 2022. 3. 12. 13:36

Enum

 서로 관련된 상수를 편리하게 선언하기 위한 것

 열거형 상수간의 비교에는 비교 연산자를 사용하지 못한다 이때 CompareTo()를 사용해 비교를 할 수 있다.

 

ex)

class Unit{
    int x,y = 0;
    enum Direction{West, East, South, North} // 혈거형 선언
    Direction direction;
    
    void init(){
        direction = Direction.East; // East로 초기화
    }
}

 

열거형의 정의된 상수를 출력하려면 다음과 같이 실행해야 한다. 

Direction[] dArr = Direction.values();

for(Direction d : Direction.values()){
    System.out.printf("%s=%d%n", d.name(), d.ordinal());
}

values()는 열거형의 모든 상수를 배열에 담아서 리턴해준다.

dArr == Direction.values()

 

열거형의 멤버추가

Enum클래스에 정의된 ordinal()은 열거형 상수가 정의된 순서를 반환하지만 열거형 안에 들어있는 값들이 불연속 적인 경우가 있다 이경우에는 열거형 상수 뒤에 원하는 값을 () 형태로 부여할 수 있다.  그리고

지정된 값을 저장할 수 있는 인스턴스 변수와 생성자를 새로 추가해 주어야 한다. 이처럼 원하는 형태의 값을 추가할 수 있지만 이후에는 그에 맞는 생성자를 만들어 주어야 한다. 

 

enum Direction {
    EAST(1, ">"), SOUTH(2,"V"), WEST(3, "<"), NORTH(4,"^");

    private static final Direction[] DIR_ARR = Direction.values();
    private final int value; // enum의 상수값임으로 final을 붙임 꼭 사용할 필요는 x
    private final String symbol;

    Direction(int value, String symbol) { // private는 생략되어있음
        this.value  = value;
        this.symbol = symbol;
    }

    public int getValue()      { return value;  }
    public String getSymbol()  { return symbol; }

    public static Direction of(int dir) {//배열의 크기 예외처리
        if (dir < 1 || dir > 4) {
            throw new IllegalArgumentException("Invalid value :" + dir);
        }
        return DIR_ARR[dir - 1];
    }

    // 방향을 회전시키는 메서드. num의 값만큼 90도씩 시계방향으로 회전한다.
    public Direction rotate(int num) {
        num = num % 4;

        if(num < 0) num +=4; // num이 음수일 때는 시계반대 방향으로 회전

        return DIR_ARR[(value-1+num) % 4]; //value-1은 (배열의 인덱스 + 회전수) % 4
    }

    public String toString() {
        return name()+getSymbol();
    }
} // enum Direction

class EnumEx2 {
    public static void main(String[] args) {
        for(Direction d : Direction.values())
            System.out.printf("%s=%d%n", d.name(), d.getValue());

        Direction d1 = Direction.EAST;
        Direction d2 = Direction.of(1);

        System.out.printf("d1=%s, %d%n", d1.name(), d1.getValue());
        System.out.printf("d2=%s, %d%n", d2.name(), d2.getValue());

        System.out.println(Direction.EAST.rotate(1));
        System.out.println(Direction.EAST.rotate(2));
        System.out.println(Direction.EAST.rotate(-1));
        System.out.println(Direction.EAST.rotate(-2));
    }
}

 

열거형의 추상메소드 

abstract class MyEnum<T extends MyEnum<T>> implements Comparable<T> {//와일드카드의 상한제한으로 T와 그 자식들만 사용
    static int id = 0;// 순서를 매기기 위한 static 상수

    int ordinal;
    String name = "";

    public int ordinal() { return ordinal; }

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

    public int compareTo(T t) {// 위에 상한 제한이 걸려있음으로 T에는 ordinal이 있다는 가정이 성립할 수 있다. 
        return ordinal - t.ordinal();
    }
}

abstract class MyTransportation extends MyEnum {
    static final MyTransportation BUS   = new MyTransportation("BUS", 100) {
        int fare(int distance) { return distance * BASIC_FARE; }
    };
    static final MyTransportation TRAIN = new MyTransportation("TRAIN", 150) {
        int fare(int distance) { return distance * BASIC_FARE; }
    };
    static final MyTransportation SHIP  = new MyTransportation("SHIP", 100) {
        int fare(int distance) { return distance * BASIC_FARE; }
    };
    static final MyTransportation AIRPLANE =
            new MyTransportation("AIRPLANE", 300) {
                int fare(int distance) { return distance * BASIC_FARE; }
            };

    abstract int fare(int distance); // 

    protected final int BASIC_FARE;

    private MyTransportation(String name, int basicFare) {
        super(name);
        BASIC_FARE = basicFare;
    }

    public String name()     { return name; }
    public String toString() { return name; }
}

class EnumEx4 {
    public static void main(String[] args) {
        MyTransportation t1 = MyTransportation.BUS;
        MyTransportation t2 = MyTransportation.BUS;
        MyTransportation t3 = MyTransportation.TRAIN;
        MyTransportation t4 = MyTransportation.SHIP;
        MyTransportation t5 = MyTransportation.AIRPLANE;

        System.out.printf("t1=%s, %d%n", t1.name(), t1.ordinal());
        System.out.printf("t2=%s, %d%n", t2.name(), t2.ordinal());
        System.out.printf("t3=%s, %d%n", t3.name(), t3.ordinal());
        System.out.printf("t4=%s, %d%n", t4.name(), t4.ordinal());
        System.out.printf("t5=%s, %d%n", t5.name(), t5.ordinal());
        System.out.println("t1==t2 ? "+(t1==t2));
        System.out.println("t1.compareTo(t3)="+ t1.compareTo(t3));
    }
}

 

'Java > Java의 정석' 카테고리의 다른 글

싱글 쓰레드 멀티 쓰레드  (0) 2022.03.15
Thread  (0) 2022.03.13
제네릭스(Generics)  (0) 2022.03.09
Set, Map  (0) 2022.03.08
Arrays  (0) 2022.03.07