목표
자바의 열거형에 대해 학습하세요.
학습할 것 (필수)
- enum 정의하는 방법
- enum이 제공하는 메소드 (values()와 valueOf())
- java.lang.Enum
- EnumSet
enum 정의하는 방법
enum은 enum : 열거형이라고 불리며, 서로 연관된 상수들의 집합이라고 불린다. 예를들어 어떤 상태의 값들을 상수로 관리할 때 Enum 으로 관리하면 좋다.
private String state; // 제출 전 = "wait" , 제출 후 = "completed"
다음과 같이 문자열로 상태값을 정의해놓으면 제출 전을 표시 할때 wait을 알기가 어렵다. 또는 대문자로 했는지 소문자로 했는지 앞글자만 대문자인지 헷갈릴 가능성이 높다. 따라서 이것은 변하지 않는 상수값으로 상태값들을 정의 해놓으면 편한데 이때 Enum을 사용한다.
Enum은 다음과 같이 정의 할 수 있다.
public enum TestStatus {
WAIT, // 제출 전
COMPLETED // 제출 후
}
class 대신 enum 예약어를 사용하고 상수들을 나열해서 정의한다. 여기서 WAIT 와 COMPLETED 는 상수지만 객체이다.
따라서 프로퍼티를 가질 수 있으며 생성자를 통해 주입이 가능하다. value 와 name 을 프로퍼티로 주면 다음과 같이 작성할 수 있다.
public enum TestStatus {
WAIT(1, "제출 전"),
COMPLETED(2, "제출 후")
;
private int value;
private String name;
TestStatus(int value, String name) {
this.value = value;
this.name = name;
}
}
enum이 제공하는 메소드 (values()와 valueOf())
Enum에 값을 가져오는 방식은 다음과 같다.
TestStatus.COMPLETED; // 직접적으로 가져오기
Enum.valueOf(TestStatus.class, "COMPLETED"); // 클래스와 이름으로 가져오기
TestStatus.valueOf("COMPLETED"); // 이름으로 가져오기
콘솔에 찍어보면 다음과 같은 결과가 나온다.
TestStatus.COMPLETED
TestStatus.COMPLETED
TestStatus.COMPLETED
Enum을 생성하는 것이 아니라 가져온다 라고 주석을 건 이유는 여러번 사용하든 같은 해쉬 코드를 가르 킨다.
System.out.println(TestStatus.COMPLETED.hashCode());
System.out.println(TestStatus.COMPLETED.hashCode());
System.out.println(TestStatus.valueOf(TestStatus.class, "COMPLETED").hashCode());
System.out.println(TestStatus.valueOf("COMPLETED").hashCode());
// 1508395126
// 1508395126
// 1508395126
// 1508395126
따라서 매번 Enum 을 생성하지 않고 가져오는 것을 알 수 있다.
생성시 새로운 hashCode 를 가지고 있는 객체들
System.out.println(new Test().hashCode());
System.out.println(new Test().hashCode());
// 972765878
// 1651945012
values() 메소드를 이용하면,
어떤 enum에 대해서 모든 값들을 가져올 수 있다.
final TestStatus[] testStatuses = TestStatus.values();
for (TestStatus testStatus : testStatuses) {
System.out.println(testStatus);
}
// TestStatus.WAIT(value=1, name=제출 전)
// TestStatus.COMPLETED(value=2, name=제출 후)
Enum 에서 가져온 값으로 할 수 있는 기능들
1. ordinal로 몇 번째 값인지 확인하기
TestStatus.COMPLETED.ordinal()
2. name 으로 이름 확인하기
TestStatus.COMPLETED.name()
3. compareTo 로 비교하기
TestStatus.COMPLETED.compareTo(TestStatus.COMPLETED)
TestStatus.COMPLETED.compareTo(TestStatus.WAIT)
// 0
// 1
java.lang.Enum
직접 만든 enum 을 상속을 받거나 할 순 없다. 기본적으로 enum 에 조상은 java.lang.Enum 이다.
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
...
}
- 기본적으로 Comparable 와 Serializable 을 구현하고 있으며 생성자는 protected 로 다음과 같이 구성되어있다.
/**
* Sole constructor. Programmers cannot invoke this constructor.
* It is for use by code emitted by the compiler in response to
* enum type declarations.
*
* @param name - The name of this enum constant, which is the identifier
* used to declare it.
* @param ordinal - The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
개발자들이 접근할 수 없으며 컴파일러에서 자동으로 호출된다.
- Object 에 clone 메소드를 사용하지 못하도록 막아 놓았다.
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
- ordinal 을 정의 한 이유
/**
* The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*
* Most programmers will have no use for this field. It is designed
* for use by sophisticated enum-based data structures, such as
* {@link java.util.EnumSet} and {@link java.util.EnumMap}.
*/
private final int ordinal;
EnumSet 와 EnumMap 같은 복잡한 데이터 구조에 사용된다.
EnumSet
다음과 같이 생성할 수 있다.
EnumSet.of(TestStatus.WAIT, TestStatus.COMPLETED); // 원하는 Enum들을 넣어서 생성
EnumSet.noneOf(TestStatus.class); // 빈 공간으로 생성
EnumSet.allOf(TestStatus.class); // 해당 Enum 에 모든 것을 생성
- EnumSet 내부 표현은 비트 벡터로 표현된다. (상수 개수가 64개 이하라면 long변수 하나로 표현한다.)
- 여기서 EnumSet 은 Enum 상수가 선언된 순서, 즉 ordinal() 메서드의 반환된 순서로 순회한다.
- 동기화가 되지 않는다.
- 모든 메소드는 산술 연산임으로 매우 빠른 작업시간을 가지고 있다.
동기화 처리 해서 Set 으로 만들기
final Set<TestStatus> testStatuses1 = Collections
.synchronizedSet(EnumSet.noneOf(TestStatus.class));
final Set<TestStatus> testStatuses2 = Collections
.synchronizedSet(EnumSet.allOf(TestStatus.class));
'스터디 > [white-ship] 자바 스터디(study hale)' 카테고리의 다른 글
13주차 과제: I/O (0) | 2021.02.20 |
---|---|
12주차 과제: 애노테이션 (0) | 2021.02.06 |
10주차 과제: 멀티쓰레드 프로그래밍 (0) | 2021.01.23 |
9주차 과제: 예외 처리 (0) | 2021.01.16 |
8주자 과제: 인터페이스 (0) | 2021.01.08 |
댓글