본 게시글은 Java의 정석 - 남궁성 을 읽고 필기한 게시글 입니다.
열거형 (enumeration) 은 관련된 변수들의 그룹을 묶어서 타입을 정의해줌으로써 다양한 활용이 가능하도록 한다.
비슷한 성격의 변수들이 갖는 값에 의미를 부여해주고 싶을 때 enum이 유용하다.
대표적인 예시로는 HTTP 프로토콜의 상태 코드가 있다.
Ok -> 200
Accepted -> 202
NotFound -> 404
BadGateWay -> 502
자바 코드로 변환
public enum HTTPStatusCode {
OK(200, "OK"),
ACCEPTED(202, "Accepted"),
NOT_FOUND(404, "Not Found"),
BAD_GATEWAY(502, "Bad Gateway");
private final int statusCode;
private final String description;
HttpStatusCode(int statusCode, String description) {
this.statusCode = statusCode;
this.description = description;
}
public int getStatusCode() {
return this.statusCode;
}
public String getDescription() {
return this.description;
}
}
enum 열거형이름 { 상수명1, 상수명2, ... }
enum Direction { EAST, SOUTH, WEST, NORTH }
int x, y;
Direction dir = Direction.EAST;
//..
switch (dir) {
case EAST: x++;
break;
case WEST: x--;
break;
case SOUTH; y++;
break;
case NORTH: y--;
break;
}
}
연산자 ==
도 사용 가능하다. (빠르다)
values()
열거형의 모든 상수를 배열에 담아 반환한다.
name()
열거형 상수의 이름을 문자열로 반환한다.
int ordinal()
열거형 상수가 정의된 순서를 반환한다.
int compareTo()
비교대상이 같으면 0, 왼쪽이 크면 양수, 우측이 크면 음수 반환
ex) dir.compareTo(Direction.WEST)
E valueOf(String name)
name과 일치하는 열거형 상수를 찾아 반환한다.
ex) Direction.valueOf("WEST") == Direction.WEST
-> true
T valueOf(Class<T> enumType, String name)
지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다.
ex) Enum.valueOf(Direction.class, "EAST") == Direction.EAST
-> true
열거형에 값을 추가할 수 있다. 열거형 상수의 이름 옆에 원하는 값을 괄호와 함께 적어주면 된다.
enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }
그리고 추가한 값을 저장할 수 있는 인스턴스 변수와 생성자를 추가해야 한다. 이는 열거형 상수를 모두 정의해준 다음 작성하면 된다.
아래 예시 코드는 String값을 하나 더 추가했고, 값을 얻을 수 있는 getValue 도 추가했다.
enum Direction {
EAST(1, ">"), SOUTH(2, "V"), WEST(3, "<"), NORTH(4, "^");
// 인스턴스 변수
private final int value; // 꼭 final일 필요는 없지면 상수이므로 붙혀준다.
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 Direction {
EAST(1, ">"), SOUTH(2, "V"), WEST(3, "<"), NORTH(4, "^");
private static final Direction[] DIR_ARR = Direction.values();
private final int value; // 꼭 final일 필요는 없지면 상수이므로 붙혀준다.
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; }
// num 만큼 90도 시계방향으로 회전한 방향을 반환한다.
public Direction rotate(int num) {
num %= 4;
if (num < 0) num += 4; // nun<0 일때 시계 반대 방향으로 회전
return DIR_ARR[(value - 1 + num) % 4];
}
@Override
public String toString() {
return name() + getSymbol();
}
}
public static void main(String[] args) {
for(Direction direction: Direction.values()) {
System.out.println(direction.name() + " " + direction.getValue() + " " + direction.getSymbol());
}
Direction d1 = Direction.EAST;
System.out.println(d1);
System.out.println(d1.name());
System.out.println(d1.rotate(2));
System.out.println(Direction.WEST.rotate(-1).name());
}
출력 결과
EAST 1 >
SOUTH 2 V
WEST 3 <
NORTH 4 ^
EAST>
EAST
WEST<
SOUTH
Enum 으로 구현할 수 있는 것은 Class로도 구현이 가능하다.
어떤 상황에서 어떤 것을 사용하는것이 좋을까?
일단 Enum와 Class의 가장 큰 차이점은, Enum은 정해진 인스턴스를 프로그램 실행 전에 선언해 놓기 때문에 프로그램 실행 도중에 인스턴스를 추가할 수 없다는 것이다.
즉, Enum은 미리 선언해 둔 고정적인 값들만 사용 할 수 밖에 없다.
고로, 런타임시에 새로운 인스턴스를 만들 필요가 없다면 Enum, 만들고 싶다면 Class를 사용하는 것이 적당하다.