본문 바로가기
java

Enum 열거형

by 킹차니 2022. 4. 15.

🟢 enum 열거형

  • 관련된 상수들을 같이 묶어 놓는 것. java는 타입에 안전한 열거형을 제공
class Card{
	static final int CLOVER = 0;
	static final int HEART = 1;
	static final int DIAMOND = 2;

	static final int TWO = 0;
	static final int THREE = 1;
	static final int FOUR = 2;
	
	final int kind;
	final int num;
}

//아래 코드는 true이다.
Card.CLOVER == Card.TWO; //true. 하지만 이둘은 의미상 엄연히 다르다.

아래처럼 enum을 사용할 수 있다

//아래처럼 바꿀 수 있다.
class Card{
	enum Kind { CLOVER, HEART, DIAMOND, SPADE } //열거형 kind를 정의앞에서부터 0, 1, 2, 3
	enum Value { TWO, THREE, FOUR } //열거형 Value를 정의

	final Kind kind; //타입이 int가 아닌 Kind
	final Value num;
}

//enum을 사용하면 아래 코드는 false이다.
Card.Kind.CLOVER == Card.Value.TWO // ERROR. 타입이 달라 둘을 비교할 수 없

 

이처럼 자바의 열거형은 값과 타입을 모두 체크한다.

 

 

 

  • 열거형을 정의하는 방법
// enum 열거형이름 { 상수명1, 상수명2, ... }
enum Direction { EAST, SOUTH, WEST, NORTH }
  • 열거형 타입의 변수를 선언하고 사용하는 방법
class Unit{
	int x, t;
	Direction dir //열거형 인스턴스 변수를 선언
	
	void init(){
		dir = Direction.EAST; // 유닛의 방향을 EAST로 초기화
	}
}
  • 열거형 상수의 비교에 == 와 compareTo() 사용가능
if(dir == Direction.EAST){...} // 이건 가능
else if(dir > Direction.WEST){...} // 이건 안됨!!!
else if (dir.compareTo(Direction.WEST){...} // 이건 가능
// 비교연산자는 사용 불가!!!!

 

 

  • 모든 열거형은 Enum(java.lang.Enum)의 자손이며, 아래의 메서드를 상속받는다.
메서드 설명
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환(0부터 시작)
T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환

 

  • values(), valueOf()는 컴파일러가 자동으로 추가
static E[] values()
static E valueOf(String name)
Direction[] dArr = Direction.values();

for(Direction d : dArr)
	System.out.println(d.name()+" - "+d.ordinal());

// EAST - 0
// SOUTH - 1
// WEST - 2
// NORTH - 3

//valueOf()에 인자로 열거형 상수 이름을 넣으면
Direction d = Direction.valueOf("WEST"); 

 

예시:

public class Ex12_5 {

    enum  Direction{
        // 0    1      2    3
        EAST, SOUTH, WEST, NORTH
    }
    
    public static void main(String[] args) {
        Direction d1 = Direction.EAST;
        Direction d2 = Direction.valueOf("WEST");
        Direction d3 = Enum.valueOf(Direction.class, "EAST");

        System.out.println("d1 = " + d1);
        System.out.println("d2 = " + d2);
        System.out.println("d3 = " + d3);

        System.out.println("d1==d2 ? " + (d1 == d2)); //false
        System.out.println("d1==d3 ? " + (d1 == d3)); //true
        System.out.println("d1.equals(d3) ? "+d1.equals(d3));
//        System.out.println("d2 > d3 ? " + (d1 > d3)); //ERROR
        System.out.println("d1.compareTo(d3) ? " + (d1.compareTo(d3)));
        System.out.println("d1.compareTo(d3) ? " + (d1.compareTo(d3)));

        switch(d1){
            case EAST ://Direction.EAST라고 쓸 수 없음
                System.out.println("The Direction is EAST."); break;
            case SOUTH ://Direction.EAST라고 쓸 수 없음
                System.out.println("The Direction is SOUTH."); break;
            case WEST ://Direction.EAST라고 쓸 수 없음
                System.out.println("The Direction is WEST."); break;
            case NORTH ://Direction.EAST라고 쓸 수 없음
                System.out.println("The Direction is NORTH."); break;
            default:
                System.out.println("INVALID direction"); break;
        }

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

    }
}

출력결과:

 

 

열거형에 멤버 변수 추가하기

이전까지는 열거형의 상수들에 순서대로 0, 1, 2, 3... 의 값들이 할당되었지만 아래처럼 직접 원하는 값을 괄호()안에 넣을 수 있다.

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

 

 

열거형의 생성자는 묵지적으로 private이므로, 외부에서 객체 생성 불가

Direction d = new Direction(1); // ERROR. 열거형의 생성자는 외부에서 호출불가

 

예시:

package lambda.nam.enumex;



public class Ex12_6 {

    enum  Direction{

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

        private final int value;
        private final String symbol;
        private static final Direction[] DIR_ARR = Direction.values();

        Direction(int value, String symbol) {
            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];
        }

        public Direction rotate(int num) {
            num = num % 4;
            if(num < 0) num += 4;
            return DIR_ARR[(value - 1 + num) % 4];
        }
    }

    public static void main(String[] args) {

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

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

출력결과:

 

 

출처: 남궁성님 유튜브 강의
https://www.youtube.com/user/MasterNKS