Java enum은 제한된 값, 상수 값들의 목록을 갖는 타입입니다.
Enum 타입은 자바에서 정말 빼놓을 수 없는 타입입니다. 나중에 얘기하겠지만, 자바에서 가장 확실하게 멀티스레드 환경에서 immutable을 보장하는 싱글톤 인스턴스로서 가장 많이 사용하는 방법 중 하나입니다.
enum의 이점과 활용법을 정리해보았습니다.
enum은 컴파일 타임에 타입 안정성을 보장합니다. 특정 범위의 값만 사용 가능하므로 컴파일 에러를 먼저 보여주어 런타임 예외를 줄일 수 있습니다.
@Getter
@RequiredArgsConstructor
public enum RoleType {
USER("사용자"),
ADMIN("관리자");
private final String desc;
}
entity 내 다른 Type의 필드를 넣지 않고 RoleType.USER
or RoleType.ADMIN
값만 넣을 수 있다.
@Enumerated(EnumType.STRING) // JPA 어노테이션
private RoleType role;
enum은 의도적으로 가독성을 높일 수 있습니다. 값들이 명시적으로 정의되어 있기 때문에 코드를 읽을 때 쉽게 이해할 수 있습니다.
enum은 관리가 용이합니다. 값이 추가되거나 변경되는 경우, 한 곳에서만 변경하면 되기 때문에 코드의 유지 보수가 용이합니다.
enum은 컴파일 타임에 정적인 값으로 변환되기 때문에, 실행 시간에서 상수 검색의 오버헤드를 줄입니다.
enum 타입은 기본적으로 직렬화 가능하므로 Serializable 인터페이스를 구현할 필요가 없고, 리플렉션 문제도 발생하지 않는다.
인스턴스가 JVM 내에 하나만 존재한다는 것이 100% 보장 되므로, Java에서 싱글톤을 만드는 가장 좋은 방법으로 권장됩니다.
✅ enum 값 비교는 그래서 euqals() 가 아닌
==
로 하면 된다. JVM 내 하나의 인스턴스로 싱글톤이 보장되기 때문에
예) 제한된 값 목록이 필요한 경우, enum을 사용하면 좋습니다. 예를 들어, 성별, 상품 상태, 제품 종류 등이 있습니다.
// ProductStatus status Enum
public void changeStatus(ProductStatus status) {
switch (status) {
case SALE:
this.status = ProductStatus.SALE;
break;
case SOLDOUT:
this.status = ProductStatus.SOLDOUT;
break;
case HIDE:
this.status = ProductStatus.HIDE;
break;
case REMOVE:
this.status = ProductStatus.REMOVE;
break;
default:
throw new IllegalArgumentException("Invalid product status: " + status);
}
}
구현 예시
public enum DayOfWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
// 주중인지 확인 DayOfWeek의 내용이니, DayOfWeek 내 처리하는 것이 클린코드적으로 좋아보임!
public boolean isWeekday() {
return this != SATURDAY && this != SUNDAY;
}
}
public static void main(String[] args) {
// 오늘이 주중인지 확인하는 메서드 만들기
DayOfWeek monday = DayOfWeek.MONDAY;
DayOfWeek saturday = DayOfWeek.SATURDAY;
// 응 맞아
// 아니야!
System.out.println(monday + " is a weekday? " + getIsWeekday(monday));
}
private static String getIsWeekday(DayOfWeek dayOfWeek) {
return dayOfWeek.isWeekday() ? "응 맞아" : "아니야!";
}
고급)
public enum CalculatorType {
CALC_A(value -> value),
CALC_B(value -> value * 10),
CALC_C(value -> value * 3),
CALC_ETC(value -> 0L);
private Function<Long, Long> expression;
CaculatorType(Function<Long, Long> expression) {this.expression = expression;}
public long caculate(long value) { return expression.apply(value); }
}
@Colum
@Enumerater(EnumType.STRING)
private CalculatorType calcType;