원래는 enum을 쓸 때, 단순히
enum Role{ ROLE_USER, ROLE_ADMIN }
이런식으로 열거해서 상수로 사용하기만 했었다.
그런데, 생각보다 활용도가 많다는 것을 알고 정리하기로 했다.
자바에서 enum은 인터페이스와 같이 독릭된 특수한 클래스로 구분된다.
힙 메모리에 저장되고, 각각의 enum 상수는 별개의 메모리 주소를 갖는다.
- 코드의 가독성을 높인다.
- 허용 가능한 값을 제한하여 type safe 하다.
- thread-safe한 싱글톤 객체로, 멀티스레딩 환경에서 안전하게 사용될 수 있다.
- switch문에서 사용할 수 있다.
Enum 객체는 메모리 힙 영역에 생성되어, 참조하여 사용한다.
Week today = Week.SUNDAY;
Enum 상수들을 values()를 통해 배열에 저장할 수 있다.Week[] days = Week.values();
Enum은 상수 하나 당 static final 인스턴스를 만든다. 무슨 소리냐면,
public enum Role {
ROLE_USER, ROLE_ADMIN
}
이렇게 enum을 만들었다면,
final class Role {
public static final Role ROLE_USER = new Role("ROLE_USER");
public static final Role ROLE_ADMIN = new Role("ROLE_ADMIN");
private String role;
private Role(String role){
this.role = role;
}
}
사실은 내부적으로 이렇게 만들어지는 것이다. 생성자가 private이기 때문에 외부에서 인스턴스를 생성할 수 없고, 필드만 get 할 수 있다.
Enum은 싱글톤으로 설계되었기 때문에, 생성자의 접근 제어자는 private으로 설정해야 한다.
Enum은 new를 사용해 인스턴스를 생성할 수 없다. Enum은 컴파일 타임에 모든 값이 고정되기 때문에 외부에서 Enum에 값을 조작하는 것은 불가능하기 때문이다.
- 데이터 그룹화
enum CreditCard {
SHINHAN("신한", Arrays.asList("Mr.Life 카드", "Deep Dream 카드", "Deep Oil 카드")),
KB("국민", Arrays.asList("톡톡D 카드", "티타늄 카드", "다담 카드")),
NH("농협", Arrays.asList("올바른 FLEX 카드", "테이크 5 카드", "NH 올원 파이카드"));
private final String Enterprise;
private final List<String> cards;
CreditCard(String name, List<String> cards) {
this.Enterprise = name;
this.cards = cards;
}
String getCard(String cardName) {
return Arrays.stream(CreditCard.values())
.filter(creditCard -> creditCard.equals(cardName))
.findFirst()
.orElseThrow(Exception::new);
}
}
카드사별로 여러 카드 종류가 있는데, enum으로 관리하고 싶다면 위와 같이 할 수 있다.
- 매서드 이용
enum Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
MULTI("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
// 클래스 생성자와 멤버
private final String symbol;
Operation(String symbol) {
this.symbol = symbol;
}
// toString을 재정의하여 열거 객체의 매핑된 문자열을 반환하도록
@Override
public String toString() {
return symbol;
}
// 열거 객체의 메소드에 사용될 추상 메소드 정의
public abstract double apply(double x, double y);
}
사용
public static void main(String[] args) {
double x = 2.5;
double y = 5.0;
// Operation 상수집합의 PLUS 상수를 정의
Operation plus = Operation.PLUS;
// enum 매핑값 출력
String name = plus.toString();
System.out.println(name); // +
// enum 확장 메소드 실행
double result = plus.apply(x, y); // 덧셈을 수행하는 메소드 (Operation.PLUS.apply(x, y) 로 해도됨)
System.out.println(result); // 7.5
// ------------------------------------------------------------------- //
// Operation 상수집합의 PLUS 상수를 정의
Operation multi = Operation.MULTI;
String name = plus.toString();
System.out.println(name); // *
// enum 확장 메소드 실행
double result2 = multi.apply(x, y); // 곱셈을 수행하는 메소드
System.out.println(result2); // 12.5
}
enum 안에 추상 매서드를 정의하고, 상수마다 추상 매서드를 오버라이딩하여 상수마다 다른 역할을 하는 매서드를 정의할 수 있다.
좋은 내용이네요. 감사합니다.