enum은 자바 가상 머신에 의해 singleton으로 생성되며 의미 있는 상수를 정의하고 프로그램의 안정성을 위해 사용됩니다.
enum CafeFoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
enum은 이러한 문제를 해결하기 위해 만들어졌습니다.
public void eat(int foodCategory) {
if (0 == foodCategory) {
System.out.println("빵");
} else if (1 == foodCategory) {
System.out.println("케이크");
} else if (2 == foodCategory) {
System.out.println("커피");
} else if (3 == foodCategory) {
System.out.println("음료");
} else {
System.out.println("존재하지않음");
}
}
이러한 메서드가 있다고 가정해봅시다. 해당 메서드는 0~3까지의 정수형 데이터를 넣으면 빵, 케이크, 커피, 음료를 출력하는 메서드입니다.
그리고 이러한 메서드를 사용하려면 일반적으로는 이렇게 할 겁니다.
eat(0);
eat(1);
메서드를 사용하는 코드만 본다면 eat(0), eat(1)이 무엇을 의미하는지 알 수 없습니다. 인자로 들어가는 0과 1의 의미를 확인하려면 eat 메서드 구현체를 직접 확인해야 겠지요.
그래서 이러한 불편함과 문제를 해결하기 위해 정수를 심볼릭 상수로 만들어서 의미를 부여했습니다.
final class FoodCategory {
public static final int BREAD = 0;
public static final int CAKE = 1;
public static final int COFFEE = 2;
public static final int BEVERAGE = 3;
}
심볼릭 상수를 정의한 FoodCategory 클래스를 만든다면 좀 더 낫습니다. 어느 정도 코드의 의미를 파악할 수 있지요.
eat(FoodCategory.BREAD);
eat(FoodCategory.CAKE);
그러나 해당 코드에는 본질적인 문제가 있습니다. eat 메서드는 정수로 된 모든 인자를 전달받을 수 있기 때문에 이러한 코드 작성도 가능합니다.
eat(-1);
eat(-100);
eat 메서드를 구현한 개발자는 eat 메서드를 이렇게 사용하라고 만들지는 않았을 겁니다. 그러나 논리적으로는 발생 할 수 있는 일입니다. 정수형 인자를 전달 받기 전에 특정 정수만 전달할 수 있도록 할 수 없으니까요.
이럴 땐 enum을 이용하면 상수에 의미를 부여하면서 전달할 수 있는 인자를 제한할 수 있습니다.
FoodCategory를 정의한 enum
enum FoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
enum 상수를 전달 받는 eat 메서드
public void eat(FoodCategory foodCategory) {
if (FoodCategory.BREAD == foodCategory) {
System.out.println("빵");
} else if (FoodCategory.CAKE == foodCategory) {
System.out.println("케이크");
} else if (FoodCategory.COFFEE == foodCategory) {
System.out.println("커피");
} else if (FoodCategory.BAVERAGE == foodCategory) {
System.out.println("음료");
}
}
eat 메서드를 FoodCategory enum에 정의된 상수만 전달받을 수 있도록 변경합니다.
eat(FoodCategory.BREAD);
eat(FoodCategory.CAKE);
그러면 eat 메서드를 호출할 때 enum에 정의된 상수만 전달할 수 있습니다. 코드의 가독성도 좋아지고 코드의 안정성도 확보됩니다.
ordinal()
ordinal() 메서드는 enum 상수에 정의된 순서값을 반환합니다.
enum FoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
enum FoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
단순히 순서값만 반환하기 때문에 정의된 상수에 위치가 달라지면 순서값이 달라질 수 있습니다. 특별한 상황이 아니라면 ordinal()에 반환된 값을 이용하여 조건을 판단하는 것을 하지 않는 것이 좋습니다.
name()
name() 메서드는 enum 상수에 정의된 이름을 반환합니다.
enum FoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
System.out.println(FoodCategory.CAKE.name());
// 출력 : CAKE
만약의 상수의 이름을 이렇게 작성했다면 다음과 같이 출력됩니다.
enum FoodCategory {
Bread, Cake, Coffee, Beverage
}
enum FoodCategory {
Bread, Cake, Coffee, Beverage
}
Enum을 다르게 정의하기
enum 상수에 특정한 값을 정의할 수 있습니다.
enum FoodCategory {
BREAD(2800),
CAKE(17000),
COFFEE(4300),
BEVERAGE(2500);
int cost;
FoodCategory(int cost) {
this.cost = cost;
}
}
상수에 특정한 값을 지정할 때는 상수의 끝맺음에 반드시 세미콜론(;)을 작성해 주어야 합니다. 그리고 특정한 값이 정의에 맞게 생성자를 반드시 정의해 주어야 합니다. 그리고 enum 내에 변수를 선언하고 생성자를 통해 값을 저장하면 다음과 같이 사용할 수 있습니다.
System.out.println(FoodCategory.BREAD.cost);
System.out.println(FoodCategory.CAKE.cost);
System.out.println(FoodCategory.COFFEE.cost);
System.out.println(FoodCategory.BEVERAGE.cost);
// 출력
2800
17000
4300
2500
하나의 특정한 값이 아니라 여러 개의 특정한 값을 지정할 수 있습니다.
enum FoodCategory {
BREAD("빵", 2800),
CAKE("케이크", 17000),
COFFEE("커피", 4300),
BEVERAGE("음료", 2500);
int name;
int cost;
FoodCategory(String name, int cost) {
this.name = name;
this.cost = cost;
}
}
System.out.println(FoodCategory.CAKE.name);
System.out.println(FoodCategory.CAKE.cost);
// 출력
케이크
17000
Enum의 생성자는 기본적으로 private이다
enum의 특성상 내부적으로 singleton 방식으로 관리하기 때문에 enum의 생성자는 기본적으로 private로 처리됩니다.
// 불가능한 코드
FoodCategory foodCategory = new FoodCategory(…);
출처 : https://www.codelatte.io/courses/java_programming_basic/EF27ZVVHZZI7SKWY
'JAVA' 카테고리의 다른 글
[JAVA]<제네릭> (0) | 2023.11.17 |
---|---|
[JAVA]Singleton 패턴 (1) | 2023.11.17 |
[JAVA]예외처리 (0) | 2023.11.10 |
[JAVA]null (0) | 2023.11.09 |
[JAVA]Object 클래스 (0) | 2023.11.07 |