열거형 - ENUM
작성일
열거형 (Enum Type)
자바는 타입 안전 열거형 패턴을 매우 편리하게 사용할 수 있는 열거형(Enum Type)
을 제공한다.
enum은 enumeration의 줄임말로 열거라는 뜻이다. 즉 어떤 항목을 나열하는 것을 뜻한다.
자바의 enum은 타입 안전성을 제공하고 코드의 가독성을 높이며 예상 가능한 값들의 집합을 표현하는데 사용된다.
Enum으로 작성한 UserRole
public enum UserRole {
GUEST, USER
}
자바의 열거형으로 작성한 UserRole
public class UserRole extends Enum {
public static final UserRole GUEST = new UserRole();
public static final UserRole USER = new UserRole();
private UserRole() {
}
}
열거형 특징
- 열거형도 클래스이다.
- 열거형은 자동으로 java.lang.Enum을 상속 받는다.
- 외부에서 임의로 생성할 수 없다.
열거형 장점
- 타입 안정성 향상: 열거형은 사전에 정의된 상수들로만 구성되므로, 유효하지 않은 값이 입력될 가능성이 없다. 만약 유효하지 않은 값을 입력할 경우 컴파일 오류가 발생한다.
- 간결성 및 일관성: 열거형을 사용하면 코드가 더 간결하고 명확해지며, 데이터의 일관성이 보장된다.
- 확장성: 새로운 타입을 추가하고 싶을 때는 ENUM에 새로운 상수를 추가하기만 하면 된다.
열거형 필드 추가
아래 코드는 자바의 열거형에 필드를 추가한 것이다.
자바의 열거형으로 작성한 UserRole - 필드 추가
public class UserRole {
public static final UserRole GUEST = new UserRole("ROLE_GUEST");
public static final UserRole USER = new UserRole("ROLE_USER");
private final String key; //필드 추가
UserRole(String key) { //생산자 추가
this.key = key;
}
}
Enum으로 작성한 UserRole - 필드 추가
public enum UserRole {
GUEST("ROLE_GUEST"),
USER("ROLE_USER");
private final String key; //필드 추가, 불변 설계
UserRole(String key) { //생산자 추가, Lombok 사용 시 @AllArgsConstructor를 사용해도 됨.
this.key = key;
}
}
- 생성자를 통해서만 key를 설정하도록 했고, 중간에 값이 변하지 않도록 불변으로 설계한다.
Enum 주요 메서드
모든 열거형은 java.lang.Enum 클래스를 자동으로 상속 받는다.
- values(): 모든 ENUM 상수를 포함하는 배열을 반환한다.
- valueOf(String name): 주어진 이름과 일치하는 ENUM 상수를 반환한다.
- name(): ENUM 상수의 이름을 문자열로 반환한다.
- ordinal(): ENUM 상수의 선언 순서(0부터 시작)를 반환한다.
- toString(): ENUM 상수의 이름을 문자열로 반환한다. name() 메서드와 유사하지만, toString()은 직접 오버라이드 할 수 있다.
참고
ordinal()의 값은 가급적 사용하지 않는 것이 좋다. 왜냐하면 이 값을 사용하다가 중간에 상수를 선언하는 위치가 변경되면 전체 상수의 위치가 모두 변경될 수 있기 때문이다.
이와 비슷한 예시로 JPA의 EnumType.ORDINAL이 있다. 예를 들어 아래와 같은 코드가 있다고 가정하자. UserRole에 GUEST, USER가 열거되어있다.
@Enumerated(value = EnumType.ORDINAL) private UserRole userRole; //GUEST, USER
ORDINAL은 GUEST, USER를 순서대로 1, 2로 데이터베이스에 저장한다. 그런데 개발 중에 GUEST, USER에서 GUEST, ADMIN, USER로 수정된다면 이 또한 순서대로 1, 2, 3으로 데이터베이스에 저장되게 된다. 이렇게 되면 순서가 꼬이게 된다. 따라서, EnumType.ORDINAL은 사용하면 안되고 EnumType.STRING을 사용해야 한다.