[JAVA] ENUM - 열거형
[JAVA] ENUM - 열거형
열거형 - ENUM
열거형(Enum Type)을 이해하기 위한 예제를 만들어보자
고객을 3개의 등급으로 나누고, 상품 구매 시 등급별로 할인을 적용한다. (소수점 버림)
- BASIC → 10% 할인
- GOLD → 20% 할인
- DIAMOND → 30% 할인
할인등급을 String
으로 표현했을 때의 문제점
- 문자열은 오타, 유효하지 않은 값 입력가능
- 타입 안정성 없음, 데이터 일관성 부족, 컴파일 시점에 오류 검출 불가
1
2
3
4
5
6
7
discount("GOLD", 10000); // 정상
discount("gold", 10000); // 오타
discount("VIP", 10000); // 존재하지 않는 등급
public int discount(int price) {
return price * discountPercent / 100;
}
문자열 상수(public static final) 사용
1
2
3
4
5
public class StringGrade {
public static final String BASIC = "BASIC";
public static final String GOLD = "GOLD";
public static final String DIAMOND = "DIAMOND";
}
장점
- 오타를 줄이고 IDE 자동완성 가능.
- 컴파일 시점에 상수 오타는 검출됨.
문제
- 여전히
String
타입이라"VIP"
같은 임의 문자열을 막을 수 없음. discount()
호출자가 반드시StringGrade
의 상수를 사용한다는 보장이 없음.
타입 안전 열거형 패턴 (Type-Safe Enum Pattern)
문자열을 대신해 타입으로 상태를 표현
열거 가능한 상태를 직접 표현해 정해진 값만 사용하게 제한
1
2
3
4
5
6
7
public class ClassGrade {
public static final ClassGrade BASIC = new ClassGrade();
public static final ClassGrade GOLD = new ClassGrade();
public static final ClassGrade DIAMOND = new ClassGrade();
private ClassGrade() {} // 외부에서 인스턴스 생성 금지
}
private 생성자의 필요성
- 외부에서
new ClassGrade()
불가능하게 막음. - 오직 내부에서 정의된 BASIC, GOLD, DIAMOND만 존재하게 제한 → “열거형”
사용
1
discount(ClassGrade.GOLD, 10000); // 타입이 ClassGrade이므로 안전
장점
- 타입 안전성:
ClassGrade
타입만 허용하므로 잘못된 값 전달 불가 - 데이터 일관성 보장
- 컴파일 타임 검증 가능
직접 구현한 타입-안전 열거형의 한계)
- 코드량이 많음
- 새로운 등급 추가 시 코드 수정 필요
- 비교적 번거롭고 자바에서 제공하는 enum보다 불편함
ENUM
이런 문제를 해결하고, 타입 안정성과 편의성을 모두 갖춘 기능이 자바 열거형(enum) 이다. enum
은 위에서 설명한 타입 안전 열거형 패턴을 자바 언어 차원에서 공식 지원하는 문법
클래스지만 제한이 많은 상수 전용 클래스라 생각
1
2
3
public enum Grade {
BASIC(10),GOLD(20),DIAMOND(20);
}
열거형 내부 상태와 메서드 활용
grade
안에 할인율 필드를 넣고, 계산 책임 이관
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public enum Grade {
BASIC(10),GOLD(20),DIAMOND(20);
private final int discountPercent;
//생성자를 통해서 필드에 값을 저장
Grade(int discountPercent) {
this.discountPercent = discountPercent;
}
//값을 조회하기 위한 메서드 열거형도 클래스라 메서드 추가 가능
public int getDiscountPercent() {
return discountPercent;
}
}
- 상태(
discountPercent
) + 동작(discount()
) = 객체 지향 - enum이 단순한 상수가 아닌, 행동도 가지는 객체처럼 사용 가능
리팩토링 효과
기존
1
int discount = DiscountService.discount(Grade.GOLD, price)
변경 후
1
int discount = Grade.GOLD.discount(price);
→ DiscountService
클래스 자체가 불필요해짐
반복 출력 및 동적 사용 가능
1
2
3
for (Grade grade : Grade.values()) {
System.out.println(grade.name() + " 등급 할인: " + grade.discount(10000));
}
values()
→ 모든 enum 상수 목록name()
→ enum 이름- 새 enum 상수가 추가되더라도 메인 코드 변경 불필요
ordinal()
의 위험성
ordinal()
은 선언 순서를 숫자로 반환 (0부터)- enum의 순서가 바뀌면 모든 값이 밀려서 버그 발생 가능
- 예:
DB
에ordinal()
저장하면 enum 순서 바뀔 때 문제 생김 - 따라서
ordinal()
대신 enum 이름 자체를 저장하거나 별도 코드 사용 권장
열거형 요약
- 열거형은 클래스다 (단, 다른 클래스 상속 불가,
Enum
만 자동 상속) - 메서드 추가 가능, 상태 보유 가능
- 캡슐화 + 타입 안정성 + 가독성 + 유지보수성 모두 잡을 수 있는 기능
- 실무에서 enum은 상태, 타입 구분, 전략 표현, DB 코드 매핑 등에 자주 사용됨
- 자바의
enum
은 singleton이므로.equals()
대신==
비교가 더 일반적
새로운 등급 추가 쉽다
1
PLATINUM(25)
1
Grade.PLATINUM.discount(10000) // → 2500
Grade
enum에 PLATINUM만 추가하면 기존 코드는 수정 없이 확장 가능
→ OCP (개방-폐쇄 원칙) 잘 지켜짐!
This post is licensed under
CC BY 4.0
by the author.