Enum아 Enum아, 너만 말고 너의 값도 유니크해 다오 Java
🇰🇷 Kor: 지금 보는 중!
🗺 Eng: Not yet!
🇯🇵 Jap: まだです。
🪖 "enum은 개인주의야."
자바에서 enum
은 열거 타입이라고 해서, 여러 선택지를 나열한 특별한 클래스 유형이죠. 그래서 기본적으로 서로 구분되는 유니크 상태입니다. 서로 구분되는 상태나 역할 등을 표현하는 데에 좋습니다.
public enum AccountStatus {
PENDING,
ACTIVE,
PROTECTED,
SUSPENDED,
SLEPT,
REMOVED
}
약간 더 구체적인 작성 양식은 이렇죠. 아마 이 글을 보시는 분들은 보통 아실 것 같습니다!
public enum 클래스_식별자 { // PascalCase
열거상수(생성자가 없다면 소괄호 생략), // UPPER_CASE
열거상수(생성자가 없다면 소괄호 생략),
...
세미콜론이 나올 때까지 콤마로 구분하여 열거상수 나열
... ;
// 세미콜론 이후로 일반 클래스처럼 필드 등을 작성합니다.
// 생성자는 외부에서 사용할 수 없습니다.
}
필드를 준 예시는 이렇겠죠. (@RequiredArgsConstructor
는 생성자를 만들어 주는 롬복 애노테이션)
@RequiredArgsConstructor
public enum AccountStatus {
PENDING(false),
ACTIVE(true),
PROTECTED(true),
SUSPENDED(true),
SLEPT(true),
REMOVED(false);
private final Boolean canSignIn;
public Boolean canSignIn() {
return canSignIn;
}
}
일반 클래스와 다르게 생성자가 static statements 블록보다 장유유서합니다.
자바의 클래스에는 클래스 로드 타임에 동작하는 정적 블록이 있습니다.
// 이렇게 생겼고요, 아는 분들은 다 아는데 모르는 분들은 말 안 해주면 모르는 그런 겁니다.
static {
// 여기에 실행문 쓰면 클래스가 처음 쓰일 때 딱 한 번 실행됩니다.
System.out.println("클래스가 메모리에 올라갈 때 실행되는 공간이오.");
}
클래스 로드 타임에 동작하니까, 동작 시점은 이렇게 되는 게 당연했어요:
클래스 "에헴, 메모리에 오르겠노라."
정적 블록 "(나는 이때 수행되어야 하는, 클래스 소유의 실행문이오.) 두둥!"
enum
도 클래스니까 정적 블록이 있는데, enum
클래스는 나열된 상수가 없으면 완성될 수 없기 때문에, 열거 상수를 만드는 각 '생성자'가 'static statements block'보다 먼저 실행됩니다.
클래스(enum) "에헴, 메모리에 오르겠노라."
열거상수들 "나도 나도 나 돋 나도나도도도 나도. 우리 없이 너네가 뭐 돼?" (생성자)
정적 블록 "선배님들 먼저 오르시지 말입니다..."
그래서 정적 블록이 실행될 때 이미 열거 상수는 생성되어 있어요. 물론 필드도요. 그래서 정적 블록에서 필드를 확인할 수 있다는 특징이 있습니다.
필드에 대한 필터는 static
블록에서 작성하면 됩니다:
static {
for (var item : values()) {
// 각 열거 항목(열거 상수)의 필드를 확인할 수 있습니다.
System.out.println("선배님들 딱 대시지 말입니다: " + item.field);
}
}
이제 유니크 필터를 간단히 씌워 봅시다.
Enum의 하위 필드의 유니크 필터
static
블럭을 사용한다는 점이 특징일 뿐, 그 내부에서 구현은 거창한 것 없이 그냥 유니크하게 관리하면 됩니다. 간단하게는 Set
타입을 사용해 중복을 체크할 수 있겠죠.
자바가 원래 클래스로드 타임은 동시성을 보장하니까 Concurrent
계열(ex: ConcurrentSkipListSet<...>
)을 안 써도 됩니다.
public enum Bits {
MaskA(1),
MaskB(1 << 1),
MaskC(1 << 2),
MaskD(1 << 3),
MaskE(1 << 4),
MaskF(1 << 5);
MaskG(1 << 6);
// Here
static {
Set<Integer> valueSet = new HashSet<>();
// values()에서 모든 열거 상수를 가져옵니다.
for (var enumItem : values()) {
// Set에서는 add 결과가 boolean이죠. (값이 잘 추가되면 true)
if (!valueSet.add(enumItem.value)) {
// 예시에서는 assert 키워드보단 Error를 던지는 걸 택했습니다.
throw new Error("중복되는 값이 없어야 합니다.");
}
}
}// static
private final int value;
Sample(int value) {
this.value = value;
}
public int value() {
return value;
}
}
Set
타입 데이터에 중복된 값이 add
되면 add
결과가 false
로 나오면서, 이를 반전한 위 조건식(!valueSet.add(...)
)은 true
가 됩니다.
즉, 중복된 값을 넣는 경우 에러를 throw
합니다. 이를 통해 중복 여부를 코드로 검증할 수 있습니다. 이 과정이 런타임에 생략되기를 원한다면 함수로 만들어 assert 함수() : "중복되는 값이 없어야 합니다.";
등으로 바꿀 수도 있죠.
Subscribe to my newsletter
Read articles from Merge Simpson directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Merge Simpson
Merge Simpson
Hello, I am Korean. Welcome, visitor. You are very cool. 안녕하세요, 저는 한국어입니다. 방문자여 환영한다. 당신은 매우 시원해.