enum은 자바 가상 머신에 의해 Singleton으로 생성되며 의미 있는 상수를 정의하고 프로그램의 안정성을 위해 사용된다.
enum을 쓰지 않을 때 메소드 호출시 인자가 가지는 의미를 파악하기 위해선 메소드의 구현체를 직접 확인해야한다. 그래서 이러한 불편함과 문제를 해결하기 위해 심볼릭 상수로 만들어서 의미를 부여해도 인자의 데이터 타입에 해당하기만 하면 모든 인자를 전달받을 수 있기 때문에 개발자가 의도하지 않는 인자를 받을 수 있는 본질적인 문제가 여전히 남아있다.
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;
}
eat(FoodCategory.BREAD);
eat(FoodCategory.CAKE);
eat(-1); //개발자가 의도하지 않은 인자 호출
eat(-100);
이럴 땐 enum을 이용하면 상수에 의미를 부여하면서 전달할 수 있는 인자를 제한 할 수 있다.
enum FoodCategory {
BREAD, CAKE, COFFEE, BEVERAGE
}
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.BREAD);
eat(FoodCategory.CAKE);
애초에 eat메소드의 인자 타입을 FoddCategory로 정의해서 FoodCategory enum에 정의된 상수만 전달받을 수 있도록 한다. 코드의 가독성도 좋아지고 안정성도 확보된다.
enum의 장점
- 매직넘버(1과 같은 숫자 상수값)를 사용할 때보다 코드가 명확해 진다.
※ 프로그래밍에서 상수로 선언하지 않은 숫자를 매직넘버라고 한다.- 잘못된 값을 사용함으로 인해 발생할수 있는 위험성이 사라진다.
FoodCategory는 enum이라는 열거형 객체이고 📌따라서 FoodCategory의 필드 BREAD는 그 자체로써 FoodCategory의 객체다. 열거형 클래스 FoodCategory가 선언된 순간, FoodCategory를 상수처럼 사용가능하다. FoodCategory.BREAD의 주소값은 컴파일타임에 정해지는 상수 객체이기 때문에 프로그램이 동작하는 동안 변할 수 없고 똑같습니다.
다시 말하면, FoodCategory의 필드 BREAD는 public static final 필드이면서 동시에 FoodCategory객체입니다.
enum 상수에 특정한 값을 정의할 수 있다.
상수에 특정한 값을 지정할 때는 상수의 끝맺음에 반드시 세미콜론을 작성해 주어야 한다. 그리고 enum내에 변수를 선언하고 생성자를 통해 값을 저장하면 값을 저장한다. 생성자의 접근제어자는 private이며 생략 가능하다.
하나가 아니라 여러 개의 특정한 값도 지정할 수 있다.
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의 특성상 내부적으로 singleton방식
으로 관리하기 때문에 enum의 생성자는 기본적으로 private로 처리된다. 그러면 new키워드로 인스턴스를 생성하는 것은 불가능하다.
// 불가능한 코드
FoodCategory foodCategory = new FoodCategory(…);