자바 5 이전에는 enum이 존재하지 않았기 때문에 interface를 사용해 이를 대체했다. 하지만 이 방식은 다음과 같이 잘못된 연산을 할 수 있는 문제를 가지고 있었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
interface Animal {
int DOG = 1;
int CAT = 2;
}
interface Person {
int MAN = 1;
int WOMAN = 2;
}
public class Main {
public static void main(String[] args) {
who(Person.MAN); // 남성
who(Animal.DOG); // 남성(잘못된 출력)
}
public static void who(int man) {
switch (man) {
case Person.MAN -> System.out.println("남성");
case Person.WOMAN -> System.out.println("여성");
}
}
}
|
cs |
하지만 enum이 도입된 이후 enum을 사용하면 위와 같은 문제가 발생하지 않는다. Animal 열거체 값은 DOG, CAT이고 Person의 값은 MAN, WOMAN이기 때문이다.
1
2
3
4
5
6
7
|
enum Animal {
DOG, CAT
}
enum Person {
MAN, WOMAN
}
|
cs |
열거체 안에 위치한 이름들을 열거체 값(Enumerated Values)라 한다.
열거체은 클래스와 유사한 성격을 띄고 있기 때문에 참조 변수에 선언할 수 있다. 하지만 참조변수는 해당 열거체 내에서 선언된 열거체 값만 대입할 수 있다.
1
2
3
4
5
|
enum Animal {
DOG, CAT
}
Animal animal = Animal.DOG; // Animal에 선언된 DOG 열거체 값 대입
|
cs |
열거체 값의 정체
아래의 예시는 열거체 값이 해당 클래스의 인스턴스라는 것을 증명한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
enum Person {
MAN, WOMAN;
private Person() {
System.out.println("default constructor called");
}
@Override
public String toString() {
return "person";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Person.MAN);
// 출력:
// default constructor called
// default constructor called
// person
}
}
|
cs |
모든 열겨형은 java.lang.Enum<E> 클래스를 상속하고 Enum<E>는 Object 클래스를 상속한다. 따라서 열겨형을 클래스로 볼 수 있다. 그리고 두 열거체 값은 Person 인스턴스를 참조하는 참조 변수다(toString 메서드 호출이 이를 증명한다).
위 예제에서 열거체 값이 두 개 이기 때문에 생성자가 두 번 호출되었다. 설명을 위해 임의적으로 private 생성자를 추가했지만 열거체은 생성자가 없으면 private 디폴트 생성자가 삽입된다. 따라서 직접 인스턴스를 생성하는 것은 불가능 하다.
열거체 값의 선언
열거체 값의 선언은 다음과 같이 ()안에 할 수 있다. 이때 해당 값을 정의하기 위해서는 해당 값을 저장할 상태 하나와 생성자가 필요하다. 이때의 생성자는 private이 아닌 default이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
enum Person {
MAN(29), WOMAN(30); // 열거형 값의 선언
private final int age;
Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return age + "";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Person.WOMAN); // toString 에서 반환: 30
System.out.println(Person.MAN.getAge()); // getAge 에서 반환: 29
}
}
|
cs |
Enum 클래스의 메소드
Enum 클래스에는 여러 메소드들이 정의되 있고 대표적인 메소드들과 사용법은 다음과 같다.
메소드 | 설명 |
static E values() | 해당 열거체의 모든 상수를 저장한 배열을 생성해 반환 |
static E valueOf(String name) | 전달된 문자열과 일치하는 해당 열거체의 상수를 반환 |
String name() | 해당 열거체 상수의 이름을 반환 |
int ordinal() | 해당 열거체 상수가 열거체 정의에서 정의된 순서를 반환 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
enum Person {
MAN(29), WOMAN(30);
private final int age;
Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return age + "";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(Person.valueOf("MAN")); // 29
System.out.println(Arrays.toString(Person.values())); // [29, 30]
System.out.println(Person.MAN.name()); // MAN
System.out.println(Person.MAN.ordinal()); // 0
}
}
|
cs |