enum, 패키지와 import, static 과 final
4. 응용 변형 예제
변형 1: 안전한 변환 메서드 (valueOf 대신 Optional)
외부 입력(요청 파라미터, 파일)을 enum 으로 바꿀 때 valueOf 는 예외를 던지고 대소문자를 가립니다. 실무는 이런 변환기를 둡니다.
public static Optional<OrderStatus> parse(String text) {
if (text == null) return Optional.empty();
String t = text.trim().toUpperCase();
for (OrderStatus s : values()) if (s.name().equals(t)) return Optional.of(s);
return Optional.empty();
}
// OrderStatus.parse(" paid ").orElseThrow(() -> new IllegalArgumentException("잘못된 상태: " + text))변형 2: EnumSet 으로 상태 집합 표현
private static final Set<OrderStatus> CANCELLABLE = EnumSet.of(OrderStatus.CREATED, OrderStatus.PAID);
private static final Set<OrderStatus> FINISHED = EnumSet.of(OrderStatus.DELIVERED, OrderStatus.CANCELLED);
public boolean cancellable() { return CANCELLABLE.contains(this); }this == CREATED || this == PAID 가 늘어나면 집합으로 바꿉니다. 조건이 한곳에 모이고, EnumSet.complementOf(FINISHED) 처럼 "진행 중인 상태 전부" 도 한 줄입니다.
변형 3: enum 이 인터페이스를 구현
public interface Discount { BigDecimal apply(BigDecimal price); }
public enum MemberGrade implements Discount {
BRONZE { public BigDecimal apply(BigDecimal p) { return p; } },
GOLD { public BigDecimal apply(BigDecimal p) { return p.multiply(new BigDecimal("0.95")); } };
}enum 은 클래스를 상속할 수는 없지만 인터페이스는 구현할 수 있습니다. 할인 정책이 "회원 등급" 이라는 고정 집합이면 enum 으로, 나중에 쿠폰처럼 무한히 늘어나면 일반 클래스로 갑니다. 중급 레슨의 추상 클래스 vs 인터페이스가 이 선택을 다룹니다.
변형 4: 상수 인터페이스 안티패턴 대신 import static
// ❌ 상수만 담은 인터페이스를 implements 해서 상수를 "상속" 받는 옛날 방식
public interface Limits { int MAX_ITEMS = 100; }
public class Cart implements Limits { ... } // Cart 의 타입 계층에 의미 없는 인터페이스가 끼어든다
// ✅ 상수 클래스 + import static
public final class Limits { private Limits() {} public static final int MAX_ITEMS = 100; }
import static Limits.MAX_ITEMS;