enum 이란
Enum이란, 서로 관련된 상수를 편리하게 선언하기 위한 기술로써, 상수 간 비교에서 리터럴만 비교한다면 Enum 간 비교에서는 타입까지 관리하기 때문에 Type Safety한 효과를 누릴 수 있다.
1 | public class Card { |
1 | true |
출처 : 남궁성 - Java의 정석
카드의 모양(Kind
)과 숫자(Num
)에 따라 상수를 Enum으로 분류했다. main()
에서 비교를 해보면, 첫번째 비교문의 결과는 콘솔에 true
로 출력된다.
그러나 두번째 비교문은 컴파일 에러가 발생했다.
연산자 문제인가 싶어서 .equals()
메서드로 다시 비교를 시도해보았다.
이 코드는 항상 false
를 반환한다고 한다. 같은 타입이 아니기 때문이다.
두번째 비교문에서 비교 대상은 Card.Kind
타입의 Clover
와 Card.Num
타입의 Zero
를 비교하고 있기 때문이다.
그래서 Enum을 사용할 경우 타입 안정성(Type Safety)를 보장받을 수 있다고 한다. 이것이 Enum을 사용하는 목적이다.
enum 정의하는 방법
1 | enum [열거형 이름] { 상수명1, 상수명2, ... } |
enum은 위와 같은 포맷으로 작성한다. 인터페이스 작성과 유사한 면이 있다는 생각이 들었다.
아래는 enum을 사용한 예제코드이다.
1 | public class Unit { |
1 | d1 = EAST |
열거형 상수 인스턴스를 각각 선언하여 비교하는 코드이다.
ordinal
이 ordinal에 대해서 주석을 통해 유추하자면 객체의 순서같았다. 영어 단어 뜻으로도 순서를 의미했다.
인텔리제이에서 다시 ordinal을 클릭해서 보니 ordinal은 열거형 상수의 정의된 순서이며, 초기값은 0이라고 한다.
Enum 클래스의 내장 메서드로 .ordinal()
을 이용하면 각 Enum 객체의 ordinal을 반환할 수 있다길래 사용해서 출력해보았다.
d1, d2, d3의 각각의 ordinal이 0, 2, 0이라고 한다.
그럼 d1.compareTo(d3)
은 d1
의 ordinal에서 d3
의 ordinal을 빼야하므로 0,
d1.compareTo(d2)
은 d1
의 ordinal에서 d2
의 ordinal을 빼므로 -2이가 된다.
enum이 제공하는 메서드 values()와 valueOf()
values()
Enum 객체를 배열에 담아 반환해주는 메서드이다.
1 | public class enumTest { |
1 | [EAST, SOUTH, WEST, NORTH] |
valueOf()
파라미터에 입력된 열거형 상수의 이름을 통해 문자열 상수에 대한 참조를 반환하는 메서드이다.
열거형 상수의 이름으로 문자열 상수에 대한 참조를 반환하는 메서드이다.
1 | Direction d1 = Direction.EAST; |
1 | true |
만약 파라미터에 들어온 문자열 값이 열거형 상수의 이름이 아닐경우, 예외(IllegalArgumentException
)을 발생시킨다.
java.lang.Enum
1 | enum Direction { |
위의 열거형 상수들의 타입은 Direction
이다. 그리고 이 Direction
은 Enum 클래스의 하위 객체이다.
이처럼 모든 Enum 타입은 Enum
클래스를 상속받는데, 그렇기 때문에 Enum 타입은 다른 클래스를 상속받을 수 없다. 다중상속이 되기 때문이다.
그래서 Enum
클래스에서 정의된 compareTo()
, values()
, valueOf()
와 같은 메서드를 사용할 수 있다.
Enum
클래스에 정의된 생성자가 있지만, 다른 클래스와 달리 접근제한자가 protected
로 선언되어있어서 Enum 클래스의 생성자는 개발자가 호출할 수 없다.
EnumSet
Enum을 위한 자료구조형 Set 인터페이스 구현체이다. EnumSet
의 상속구조는 다음과 같다.
EnumSet
의 주요특징은 아래와 같다.
AbstractSet
클래스를 상속하며, Set 인터페이스를 구현한다.- 오직 열거형 상수만을 값으로 가질수 있으며, 모든 값은 같은 Enum Type이어야 한다. (제네릭으로 강제하는것이 좋음)
- Null 값을 가지지 않는다.
- ordinal(열거형 상수가 정의된 순서)대로 요소가 저장된다.
- thread-safe하지 않으므로
Collections.synchronizedMap
을 사용하거나 외부에서 동기화를 구현해야한다.
EnumSet 주요 메서드
EnumSet.allOf()
Enum
클래스의 열거형 상수를 EnumSet
집합으로 모두 가져오는 메서드이다.
1 | public class LiveStudy { |
1 | [EAST, SOUTH, WEST, NORTH] |
EnumSet.of()
파라미터로 들어온 열거형 상수를 EnumSet
집합으로 반환하는 메서드이다.
파라미터 순대로 EnumSet
에 저장되지 않고, ordinal대로 저장된다.
1 | public class LiveStudy { |
1 | [EAST, SOUTH, NORTH] |
complementOf()
Enum 타입의 전체 열거형 상수중 파라미터로 들어온 EnumSet 인스턴스에 없는 열거형 상수를 EnumSet 으로 반환한다.
1 | public class LiveStudy { |
1 | [EAST, WEST] |
range()
2개의 파라미터로 들어온 열거형 상수 사이의 열거형 상수들을 EnumSet
집합으로 반환한다. 범위의 인덱스는 ordinal을 따른다.
1 | public class LiveStudy { |
1 | [SOUTH, WEST, NORTH] |
noneOf()
파라미터로 들어온 열거형 클래스의 빈값을 EnumSet
타입으로 반환한다.
1 | public class LiveStudy { |
1 | [] |
copyOf()
EnumSet
객체를 복사하는 메서드이다.
1 | public class LiveStudy { |
1 | [EAST, WEST, NORTH] |
add(), remove()
열거형 상수를 더하고 빼는 메서드이다.
1 | public class LiveStudy { |
1 | [EAST, SOUTH, WEST] |
함께 보면 좋을 글