Java - enum
Java의 enum을 알면 효율적인 프로그래밍이 가능해 보여 이에 대해 알아보고자 한다.
열거형 선언
JDK 1.5부터 사용 가능한 기능이다.
상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 유용하다.
정의는 아래와 같이 한다. 끝에 세미콜론(;)이 없는 것에 주의해야 한다.
enum 열거형이름 {상수명1, 상수명2, ... }
Enum 클래스
enum에 대해 자세히 알아보기 전에 모든 열거형의 조상인 Enum 클래스를 먼저 알아보자.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Enum.html
Enum (Java SE 11 & JDK 11 )
docs.oracle.com
Enum는 Serializable, Comparable 인터페이스를 구현한 클래스이다.
정의된 메서드는 아래와 같다.
name() | 열거형 상수의 이름을 문자열로 반환 |
valueOf(Class<T> enumType, String name) | 지정된 열거형에서 name과 일치하는 열거형 상수를 반환 |
getDeclaringClass() | 열거형의 Class객체를 반환 |
equals(Object other) | 지정된 개체가 열거 상수와 같으면 true 반환 |
compareTo(E o) | 열거형을 지정된 개체와 비교 후 양수, 0, 음수 반환 같은 열거형의 다른 열거형 상수와만 비교 가능 |
ordinal() | 열거 상수 반환 |
ordinal()는 열거형 상수가 정의된 순서를 0부터 정수로 반환한다.
이를 활용한 코드와 출력 결과이다.
enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}
public class EnumPractice {
public static void main(String[] args) {
Week week = Week.WEN;
System.out.println("name(): " + week.name());
System.out.println("valueOf(): " + Week.valueOf("WEN"));
System.out.println("valueOf(): " + Enum.valueOf(Week.class, "WEN"));
System.out.println("valueOf(): " + Enum.valueOf(week.getDeclaringClass(), "WEN"));
System.out.println("getDeclaringClass(): " + week.getDeclaringClass() + "\n");
System.out.println("equals(): " + week.equals(Week.WEN));
System.out.println("compareTo(): " + week.compareTo(Week.MON) + "\n");
System.out.println("ordinal(): " + week.ordinal());
}
}
크게 어려운 부분은 없다.
추가로 문서에는 없지만 모든 열거형에 컴파일러가 자동으로 추가해 주는 메서드가 있다.
values() | 열거형의 모든 상수를 배열에 담아 반환 |
valueOf(String name) | 열거형 상수 이름으로 문자열 상수에 대한 참조를 얻음 |
enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}
public class EnumPractice {
public static void main(String[] args) {
Week[] week = Week.values();
for(Week w : week) {
System.out.println(w);
}
System.out.println("valueOf(String s): " + Week.valueOf("WEN"));
System.out.println("valueOf(String s)의 Class: " + Week.valueOf("WEN").getClass());
}
}
특히 values()는 활용성이 높다고 생각한다.
열거형 활용
메서드를 알았으니 이제 여러 활용법을 알아보자.
기본
가장 기본적인 활용은 아래와 같이 바로 사용하거나 열거형에 맞는 변수를 선언하고 사용하는 것이다.
enum Week {MON, TUE, WEN, THU, FRI, SAT, SUN}
enum Direction {EAST, WEST, SOUTH, NORTH}
public class EnumPractice {
public static void main(String[] args) {
System.out.println(Week.FRI); //바로 사용
Direction dir = Direction.EAST;
System.out.println(dir); //변수 선언 후 사용
}
}
switch문
열거형은 switch문에도 활용할 수 있다.
이때 switch문의 조건식엔 '열거형.상수'가 아니라 '상수'만 적어야 한다는 점이다.
'열거형.상수'를 입력하면 컴파일 에러가 발생한다.
enum Direction {EAST, WEST, SOUTH, NORTH}
public class EnumPractice {
public static void main(String[] args) {
Direction dir = Direction.EAST;
switch (dir) {
case EAST:
System.out.println("EAST");
break;
case WEST:
System.out.println("WEST");
break;
case SOUTH:
System.out.println("SOUTH");
break;
case NORTH:
System.out.println("NORTH");
break;
}
}
}
상수
ordinal()을 활용하면 각 열거형 상수에 대해 정수를 반환한다.
하지만 이 값은 직접 선언한 것이 아니기 때문에 활용을 권장하지 않는다.
이를 대신해 괄호를 이용해 각 열거형 상수에 대해 추가적인 정보를 저장할 수 있다.
아래 코드는 각 요일마다 무작위로 상수를 담은 것이다.
이렇게 활용할 때 주의할 점은
1. 세미콜론(;)을 붙여야 한다.
2. 인스턴스 변수와 생성자를 구현해야 한다.
이다.
enum Week {
MON(1), TUE(3), WEN(4), THU(6), FRI(7), SAT(8), SUN(10); //세미콜론
private final int value; //인스턴스 변수
Week(int value) { //생성자
this.value = value;
}
public int getValue() {
return value;
}
}
public class EnumPractice {
public static void main(String[] args) {
Week week = Week.WEN;
System.out.println(week.getValue());
}
}
출력 결과는 "4"이다.
생성자를 구현했으면 아래와 같이 활용할 수 있지 않을까 생각이 드는데 컴파일 에러가 발생한다.
그 이유는 enum의 생성자는 default 제어자가 private이기 때문이다.
괄호 안에 여러 개의 변수를 활용할 수도 있다.
enum Week {
MON(1, "월요일"), TUE(3, "화요일"), WEN(4, "수요일"),
THU(6, "목요일"), FRI(7, "금요일"), SAT(8, "토요일"), SUN(10, "일요일");
private final int value;
private final String korean;
Week(int value, String korean) {
this.value = value;
this.korean = korean;
}
public int getValue() {
return value;
}
public String getKorean() {
return korean;
}
public String toString() {
return korean + " " + value;
}
}
public class EnumPractice {
public static void main(String[] args) {
Week week = Week.WEN;
System.out.println(week.getValue());
System.out.println(week.getKorean());
System.out.println(week.toString());
}
}
활용성이 매우 높다.
추상 메서드
열거형 클래스에 추상 메서드를 활용할 수도 있다.
열거형 상수의 경우마다 다른 메서드를 구현해야 하는 경우가 있을 수 있기 때문이다.
enum Week {
MON(1, "월요일") {String schedule() {return basic + "독서하기";}},
TUE(3, "화요일") {String schedule() {return basic + "산책하기";}},
WEN(4, "수요일") {String schedule() {return basic + "게임하기";}},
THU(6, "목요일") {String schedule() {return basic + "공부하기";}},
FRI(7, "금요일") {String schedule() {return basic + "다시자기";}},
SAT(8, "토요일") {String schedule() {return basic + "요리하기";}},
SUN(10, "일요일") {String schedule() {return basic + "명상하기";}};
abstract String schedule();
protected final String basic = "일어나서 ";
private final int value;
private final String korean;
Week(int value, String korean) {
this.value = value;
this.korean = korean;
}
public int getValue() {
return value;
}
public String getKorean() {
return korean;
}
public String toString() {
return korean + " " + value;
}
}
public class EnumPractice {
public static void main(String[] args) {
for(Week week : Week.values())
System.out.println(week.schedule());
}
}