[스터디할래 11] Enum
이 글은 ‘백기선’ 개발자님과 함께하는 온라인 자바 스터디에 참여하여 준비/학습한 내용을 정리하는 글입니다.📚
- 11주차 : https://github.com/whiteship/live-study/issues/11
- 목표 : 자바의 열거형에 대해 학습하세요.
정리는 Java Language Spec - Enum를 기반으로 하였습니다.
enum 정의하는 방법
Enum
은 미리 정해진 값을 변수로 저장해두는 특별한 타입이다.- 미리 지정해둔 변수값들만 사용할 수 있다.
public enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
- 위와 같이 생성하며, 선언된
SUNDAY, MONDAY ...
변수들을 ‘enum 상수’라고 표현한다. - 상수를 의미하는 enum 필드명은 주로 대문자를 사용한다.
- 모든 enum은 내부적으로
java.lang.Enum
을 상속한다. 자바에서는 다중상속이 지원되지 않기 때문에 enum은 다른 클래스를 상속할 수 없다. - enum 선언에
abstract
나final
접근제어자를 붙이면 컴파일 에러이다. - enum 타입은 선언된 상수들 이외에는 다른 인스턴스가 존재하지 않는다. 이넘 타입을 객체화하려고 하면 컴파일 에러이다.
- 이 외에도 내부적으로
final clone
, Reflective instantiation 금지 등 여러 방법으로 단일 객체만을 보장한다.
- 이 외에도 내부적으로
java.lang.Enum
- enum 타입이 공통으로 상속하는 base class 이다.
enum이 제공하는 메소드 (values()와 valueOf())
- enum을 정의하면 내부적으로
Enum
클래스를 상속하기 때문에Enum
클래스의 다양한 메서드를 사용할 수 있다.
clone()
- enum은 단일 객체만 존재해야 하는 싱글턴을 지향하기 때문에
clone
메서드는 사용 시CloneNotSupportedException
를 throw한다.
name()
- 이넘 상수를 정의할 때 사용한 이름을 리턴한다.
toString()
과 구별되어야 한다.name()
은 상수의 정확한 이름을 사용해야만 하는 특수한 경우에만 사용하고, 그 외에는 일반적으로 유저가 재정의한toString()
를 사용해야 한다. - 예를 들어 아래 예제에서
Day.SUN
이넘에서name()
메서드는"SUN"
을 리턴하고,toString()
메서드는"sunday"
를 리턴한다.public enum Day { SUN("sunday"), MON("monday"), TUE("tuesday"), WED("wednesday"), THU("thursday"), FRI("friday"), SAT("saturday"); String name; Day(String name) { this.name = name; } public String toString() { return this.name; } }
ordinal()
- 이넘 상수의 선언 position 을 리턴한다. 이넘은 내부적으로 선언된 순서에 따라 번호가 부여되는데, 사실상 이 메서드는 프로그래머가 사용할 일도 없고 사용해서는 안된다.
- Effective Java, Item 31 : ordinal 대신 객체 필드를 사용하라에 따르면 ordinal 을 사용하지 않고 번호를 저장하는 별도 필드를 생성하자.
toString()
- enum 상수의 이름을 리턴하도록 정의되어있으나, 프로그래머가
override
해서 사용해야 한다.
values()
- enum에 정의된 값을 선언된 순서대로 배열로 리턴한다.
for-each
로 이넘 값을 순회할 때에 자주 사용된다.
valueOf()
- enum 이름에 정의된 값에 해당하는 이넘 상수를 리턴한다.
EnumSet
- enum 타입과 함께 쓰는
Set
의 구현 타입이다.EnumSet
의 요소는 하나의 특정Enum
타입이어야 한다. - 내부적으로 bit vector로 표현되어 있어서 시/공간 퍼포먼스가 띄어나다. 대량 작업인
containsAll
,retainAll
같은 메서드도 0, 1로 계산하면 되니 매우 빠르다. - 단, 다른 collection 구현체 처럼 synchronized 가 아니기 때문에, 멀티스레드 환경에서는 동기화를 외부적으로 지원해야 한다.