📌 장점 : 클래스를 정의해서 정해진 객체만 사용가능하게 제한
📌 단점 : 많은 코드를 작성해야한다. (접근제한자, 반환타입 등)
"타입 안전 열거형 패턴"을 더 간편하게 사용하기 위해 자바는 Enum 이라는 개념을 제공한다.
enum 은 enumeration 의 줄임말로 '열거' 라는 뜻으로 항목을 나열한다는 의미이다. enum을 사용하면 문자열이나 숫자 상수 대신, 의미가 분명한 이름을 가진 상수를 사용하게 되므로 코드의 가독성과 안정성이 높아지고, 예상 가능한 값들의 집합을 표현하는데 사용된다. 또 컴파일 시점에 잘못된 값 입력을 방지해 런타임 오류를 막을 수 있다.
class대신 enum 을 사용한다.java.lang.Enum 에 enum 의 기능과 틀이 이미 정의되어 있고, 모든 enum은 이를 상속받기 때문에, 개발자는 이름만 선언해도 자동으로 상수 인스턴스가 만들어진다.package enumeration.ex3;
public enum Grade {
BASIC, GOLD, DIAMOND
}
📌 장점 : 타입의 안정성, 간결성 및 일관성, 확장성 (추가하고 싶을 때 Enum 에 새로운 상수를 추가 하면 됨)

package enumeration.ex3;
import java.util.Arrays;
public class EnumMethodMain {
public static void main(String[] args) {
Grade[] values = Grade.values();
System.out.println("values = "+ Arrays.toString(values));
for (Grade value : values) {
System.out.println("name = "+ value.name() + ", ordinal = "+ value.ordinal());
}
// String 을 ENUM 으로 변환
String input = "GOLD";
Grade gold = Grade.valueOf(input);
System.out.println("gold = "+ gold);
}
}
values() : 모든 Enum 상수를 배열 형태로 반환한다.valueOf() : 배열 안에 주어진 문자와 일치하는 상수를 반환한다.ordinal() : 상수의 선언 순서를 반환한다. (웬만하면 사용❌)name() : 상수의 이름을 문자열로 반환한다.toString() : 상수의 이름을 문자열로 반환하며 재정의가 가능하다.해당하는 등급에 맞게 할인율을 적용하려고 한다. enum 을 사용해서 코드를 작성해보자.
package enumeration.ref2;
public enum Grade {
BASIC(10), GOLD(20), DIAMOND(30); // 상수 초기화
private final int discountPercent;
Grade(int discountPercent) { // 생성자
this.discountPercent = discountPercent;
}
public int getDiscountPercent() { // 메서드
return discountPercent;
}
}
➡️ 각각의 등급(enum 상수)에 할인율을 생성자 인자(매개변수)로 넣어 초기화한다. 할인율을 담을 변수를 enum 내부에 한 번만 선언해두고, 각 상수 생성 시 값을 대입해 관리한다.
package enumeration.ref2;
public class DiscountService {
public int discount(Grade classGrade, int price) {
return price * classGrade.getDiscountPercent() / 100;
}
}
➡️ 상품 가격에 해당하는 등급의 할인율을 적용하는 클래스다.
package enumeration.ref2;
public class ClassGradeRefMain2 {
public static void main(String[] args) {
int price = 10000;
// 호출이 조건에 맞는지 비교하고 그에 맞는 할인율을 대입해 계산하는 방법 vs 조건에 그에 맞는 할인율을 대입해두고 호출하면 바로 계산에 돌입하기
DiscountService discountService = new DiscountService();
int basic = discountService.discount(Grade.BASIC, price);
int gold = discountService.discount(Grade.GOLD , price);
int diamond = discountService.discount(Grade.DIAMOND, price);
System.out.println("BASIC 등급의 할인 금액 : " + basic);
System.out.println("GOLD 등급의 할인 금액 : " + gold);
System.out.println("DIAMOND 등급의 할인 금액 : " + diamond);
}
}
➡️ 등급별 상수enum와 가격을 discount() 메서드에 전달하면, 메서드는 해당 등급의 할인율을 적용해 계산을 수행하고 결과 금액을 반환한다. 이후 메인 메서드에서 이 값을 출력해 등급별 할인 금액을 확인한다.
이 코드는 일부 보완되었지만 여전히 리팩토링 여지가 있다. 현재 할인 계산 클래스는 ClassGrade의 메서드를 호출하기만 하는 중간자 역할로, 자체 책임이 없다. 할인율의 선언과 계산 책임을 ClassGrade로 통합하면 캡슐화가 강화되고 사용도 더 직관적이다.
package enumeration.ref3;
public enum Grade {
BASIC(10), GOLD(20), DIAMOND(30); // 상수 초기화
private final int discountPercent;
Grade(int discountPercent) { // 생성자
this.discountPercent = discountPercent;
}
public int getDiscountPercent() { // 메서드
return discountPercent;
}
public int discount(int price) { // 계산하는 메서드 추가 ‼️
return price * discountPercent / 100;
}
}
➡️ 할인율과 관련된 기능을 하나의 클래스에 정의했다.
package enumeration.ref3;
public class EnumRefMain3_1 {
public static void main(String[] args) {
int price = 10000;
System.out.println("BASIC 등급의 할인 금액 : " + Grade.BASIC.discount(price));
System.out.println("GOLD 등급의 할인 금액 : " + Grade.GOLD.discount(price));
System.out.println("DIAMOND 등급의 할인 금액 : " + Grade.DIAMOND.discount(price));
}
}
➡️ 할인율 계산이 enum 내부의 책임으로 들어가면서, 단순히 연결만 하던 DiscountService 클래스는 불필요해졌다.
이제 각 등급 상수에서 직접 할인율을 계산하므로, 메서드 호출을 출력문에서 바로 실행할 수 있어 코드가 훨씬 간결해졌다.
📌 중복되는 코드 지우기
package enumeration.ref3;
public class EnumRefMain3_3 {
public static void main(String[] args) {
int price = 10000;
Grade[] grades = Grade.values(); // 배열로 객체들 싹 가져와서
for (Grade grade : grades) { // 배열과 price 로 호출을 반복한다.
printDiscount(grade,price);
}
}
private static void printDiscount(Grade grade, int price) {
System.out.println(grade.name() + " 등급의 할인 금액 : "+ grade.discount(price)); // 출력마다 달라지는 이름은 name() 으로 해결했다
}
}
➡️ 메서드 호출 부분과 출력문은 중복되는 코드들이 있다. 이 둘을 반복문으로 더 간결하게 만들었다.
인증등급을 입력받아서 각 등급별로 접근할 수 있는 화면을 출력한다. 밑의 main 클래스를 보고 enum 을 작성하자.
package enumeration.test.http;
import java.util.Scanner;
public class HttpStatusMain {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("HTTP CODE : ");
int httpCodeInput = scanner.nextInt();
HttpStatus status = HttpStatus.findByCode(httpCodeInput);
if (status == null) {
System.out.println("정의되지 않은 코드");
} else {
System.out.println(status.getCode()+" "+status.getMessage());
System.out.println("isSuccess = "+ status.isSuccess());
}
}
}
답안 :
package enumeration.test.http;
public enum HttpStatus {
OK(200, "OK")
,BAD_REQUEST(400, "Bad Request")
,NOT_FOUND(404, "Not Found")
,INTERNAL_SERVER_ERROR(500, "Internal Server Error");
private final int code; // final 빼먹지 말것❗️
private final String message;
HttpStatus(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
// 코드 값을 받아서 해당하는 코드를 가진 등급을 반환하는 메서드
public static HttpStatus findByCode(int code) {
for (HttpStatus status : values()) {
if (status.getCode() == code) { // static.getCode 를 생각못했다.
return status;
}
}
return null; // 해당하는 등급이 없을 때
}
public boolean isSuccess() { // 코드 입력 가능 범위로 성공 판단
return code >= 200 && code <= 299;
}
}