열거형이란?
열거형(Enum)은 서로 연관된 상수들의 집합이라고 할 수 있다. 자바의 열거형은 C언어의 열거형과 달리 값과 타입을 함께 비교하기 때문에 보다 논리적인 오류를 줄일 수 있다.
class Card {
enum Kind { CLOVER, HEART, DIAMOND, SPADE } // 열거형 Kind를 정의
enum Value { TWO, THREE, FOUR } // 열거형 Value를 정의
final Kind kind = Kind.CLOVER;
final Value value = Value.TWO;
}
자바의 열거형은 '타입에 안전한 열거형(typesafe enum)'이기 때문에 실제값이 같아도 타입이 다르면 컴파일 에러가 발생한다. 이처럼 값뿐만 아니라 타입까지 체크하기 때문에 타입에 안전하다고 하는 것이다.
if(Card.CLOVER == Card.TWO) // true지만 false여야 의미상 맞음
if(Card.Kind.CLOVER == Card.Value.TWO) // 컴파일 에러. 값은 같지만 타입이 다름
가장 중요한 것은 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일해야 한다는 것이다. 하지만 열거형 상수를 사용하면 기존의 소스를 컴파일 하지 않아도 된다.
정의하는 방법
다음과 같이 괄호안에 상수의 이름을 나열함으로써 열거형을 정의할 수 있다.
enum 열거형이름 { 상수명1, 상수명2, ... }
enum Direction { EAST, SOUTH, WEST, NORTH }
이렇게 정의한 열거형의 상수를 사용하기 위해선 '열거형이름.상수명'이다. 위의 예제에선 Direction.EAST 등으로 사용할 수 있다. 이는 클래스의 static 변수를 참조하는 것과 동일하다.
열거형 상수 간의 비교에는 '=='이나 equals( ) 등을 사용할 수 있다. 그러나 '<', '>'와 같은 비교연산자는 사용할 수 없고 compareTo( )는 사용할 수 있다. 이는 열거형 상수가 객체이기 때문이다. 또한, switch문의 조건식에도 열거형을 사용할 수 있다.
if(dir == Direction.EAST) {
// ...
} else if (dir.equals(Direction.NORTH)) {
// ...
} else if (dir > Direction.SOUTH) { // 에러 발생
// ...
} else if (dir.compareTo(Direction.WEST) > 0) {
// ...
}
Java.lang.Enum
Enum클래스는 모든 열거형의 조상이다. 따라서 모든 열거형은 다음과 같은 메소드를 상속받는다.
메소드 | 설명 |
T[] values | 열거형의 모든 상수를 배열에 담아 반환한다. |
Class<E> getDeclaringClass() | 열거형의 Class객체를 반환한다. |
String name() | 열거형 상수의 이름을 문자열로 반환한다. |
int ordinal() | 열거형 상수가 정의된 순서를 반환한다(0부터 시작). |
T valueOf(Class<T> enumType, String name) | 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다. |
이를 응용하여 다음과 같이 열거형에 정의된 모든 상수를 출력할 수 있다.
Direction[] dArr = Direction.values();
for(Direction d : dArr) {
System.out.printf("%s = %d%n", d.name(), d.ordinal());
}
//output
EAST = 0
SOUTH = 1
WEST = 2
NORTH = 3
EnumSet
EnumSet은 Enum클래스로 작동하는 Set컬렉션이다. EnumSet은 Set인터페이스를 구현하고, AbstractSet을 상속한다. 이러한 EnumSet의 장점은 내부적으로 비트 벡터로 구성되어 있기 때문에 모든 메서드가 산술 비트 연산을 사용하여 구현되어 일반적인 연산이 매우 빠르게 계산된다는 것이다.
EnumSet은 다음과 같은 메소드를 제공한다. 다음의 예제를 통해 살펴보자.
- allOf( ): 모든 요소를 포함하는 EnumSet을 만든다.
- noneOf( ): 해당하는 열거형 타입의 빈 컬렉션을 갖는 EnumSet을 만든다.
- of( ): 들어갈 요소를 직접 입력하여 EnumSet을 생성한다.
- complementOf( ): 인자로 주어지는 EnumSet의 원소를 제거하고 새로운 EnumSet을 만든다.
- copyOf( ): 다른 EnumSet의 모든 요소를 복사하여 새로운 EnumSet을 만든다.
- add( ): EnumSet에 원소를 추가한다.
- remove( ): EnumSet에 원소를 제거한다.
import java.util.EnumSet;
enum Direction { EAST, SOUTH, WEST, NORTH}
public class EnumEx {
public static void main(String[] args) {
// 1. allOf
EnumSet<Direction> se1 = EnumSet.allOf(Direction.class);
se1.forEach(System.out::println);
// 2. noneOf
EnumSet<Direction> se2 = EnumSet.noneOf(Direction.class);
System.out.println(se2);
// 3. of
EnumSet<Direction> se3 = EnumSet.of(Direction.EAST, Direction.SOUTH);
System.out.println(se3);
// 4. copyOf
EnumSet<Direction> se4 = EnumSet.copyOf(se3);
System.out.println(se4);
// 5.complementOf
EnumSet<Direction> se5 = EnumSet.complementOf(EnumSet.of(Direction.EAST));
System.out.println(se5);
// 6. contains
boolean isContain = se3.contains(Direction.WEST);
System.out.println(isContain);
// 7.remove
se3.remove(Direction.EAST);
System.out.println(se3);
}
}
//output
// 1. allOf
EAST
SOUTH
WEST
NORTH
// 2. noneOf
[]
// 3. of
[EAST, SOUTH]
// 4. copyOf (from 3)
[EAST, SOUTH]
// 5. complementOf (from 3)
[SOUTH, WEST, NORTH]
// 6. contains (from 3)
false
// 7. remove (from 3)
[SOUTH]
참고
자바의 정석(남궁성 저)
'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글
[Java] 스터디 13주차: I/O (0) | 2021.09.02 |
---|---|
[Java] 스터디 12주차: 애노테이션 (0) | 2021.08.19 |
[Java] 스터디 10주차: 쓰레드 (0) | 2021.08.17 |
[Java] 스터디 9주차: 예외처리 (0) | 2021.07.29 |
[Java] 스터디 8주차: 인터페이스 (0) | 2021.07.22 |
열거형이란?
열거형(Enum)은 서로 연관된 상수들의 집합이라고 할 수 있다. 자바의 열거형은 C언어의 열거형과 달리 값과 타입을 함께 비교하기 때문에 보다 논리적인 오류를 줄일 수 있다.
class Card {
enum Kind { CLOVER, HEART, DIAMOND, SPADE } // 열거형 Kind를 정의
enum Value { TWO, THREE, FOUR } // 열거형 Value를 정의
final Kind kind = Kind.CLOVER;
final Value value = Value.TWO;
}
자바의 열거형은 '타입에 안전한 열거형(typesafe enum)'이기 때문에 실제값이 같아도 타입이 다르면 컴파일 에러가 발생한다. 이처럼 값뿐만 아니라 타입까지 체크하기 때문에 타입에 안전하다고 하는 것이다.
if(Card.CLOVER == Card.TWO) // true지만 false여야 의미상 맞음
if(Card.Kind.CLOVER == Card.Value.TWO) // 컴파일 에러. 값은 같지만 타입이 다름
가장 중요한 것은 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일해야 한다는 것이다. 하지만 열거형 상수를 사용하면 기존의 소스를 컴파일 하지 않아도 된다.
정의하는 방법
다음과 같이 괄호안에 상수의 이름을 나열함으로써 열거형을 정의할 수 있다.
enum 열거형이름 { 상수명1, 상수명2, ... }
enum Direction { EAST, SOUTH, WEST, NORTH }
이렇게 정의한 열거형의 상수를 사용하기 위해선 '열거형이름.상수명'이다. 위의 예제에선 Direction.EAST 등으로 사용할 수 있다. 이는 클래스의 static 변수를 참조하는 것과 동일하다.
열거형 상수 간의 비교에는 '=='이나 equals( ) 등을 사용할 수 있다. 그러나 '<', '>'와 같은 비교연산자는 사용할 수 없고 compareTo( )는 사용할 수 있다. 이는 열거형 상수가 객체이기 때문이다. 또한, switch문의 조건식에도 열거형을 사용할 수 있다.
if(dir == Direction.EAST) {
// ...
} else if (dir.equals(Direction.NORTH)) {
// ...
} else if (dir > Direction.SOUTH) { // 에러 발생
// ...
} else if (dir.compareTo(Direction.WEST) > 0) {
// ...
}
Java.lang.Enum
Enum클래스는 모든 열거형의 조상이다. 따라서 모든 열거형은 다음과 같은 메소드를 상속받는다.
메소드 | 설명 |
T[] values | 열거형의 모든 상수를 배열에 담아 반환한다. |
Class<E> getDeclaringClass() | 열거형의 Class객체를 반환한다. |
String name() | 열거형 상수의 이름을 문자열로 반환한다. |
int ordinal() | 열거형 상수가 정의된 순서를 반환한다(0부터 시작). |
T valueOf(Class<T> enumType, String name) | 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다. |
이를 응용하여 다음과 같이 열거형에 정의된 모든 상수를 출력할 수 있다.
Direction[] dArr = Direction.values();
for(Direction d : dArr) {
System.out.printf("%s = %d%n", d.name(), d.ordinal());
}
//output
EAST = 0
SOUTH = 1
WEST = 2
NORTH = 3
EnumSet
EnumSet은 Enum클래스로 작동하는 Set컬렉션이다. EnumSet은 Set인터페이스를 구현하고, AbstractSet을 상속한다. 이러한 EnumSet의 장점은 내부적으로 비트 벡터로 구성되어 있기 때문에 모든 메서드가 산술 비트 연산을 사용하여 구현되어 일반적인 연산이 매우 빠르게 계산된다는 것이다.
EnumSet은 다음과 같은 메소드를 제공한다. 다음의 예제를 통해 살펴보자.
- allOf( ): 모든 요소를 포함하는 EnumSet을 만든다.
- noneOf( ): 해당하는 열거형 타입의 빈 컬렉션을 갖는 EnumSet을 만든다.
- of( ): 들어갈 요소를 직접 입력하여 EnumSet을 생성한다.
- complementOf( ): 인자로 주어지는 EnumSet의 원소를 제거하고 새로운 EnumSet을 만든다.
- copyOf( ): 다른 EnumSet의 모든 요소를 복사하여 새로운 EnumSet을 만든다.
- add( ): EnumSet에 원소를 추가한다.
- remove( ): EnumSet에 원소를 제거한다.
import java.util.EnumSet;
enum Direction { EAST, SOUTH, WEST, NORTH}
public class EnumEx {
public static void main(String[] args) {
// 1. allOf
EnumSet<Direction> se1 = EnumSet.allOf(Direction.class);
se1.forEach(System.out::println);
// 2. noneOf
EnumSet<Direction> se2 = EnumSet.noneOf(Direction.class);
System.out.println(se2);
// 3. of
EnumSet<Direction> se3 = EnumSet.of(Direction.EAST, Direction.SOUTH);
System.out.println(se3);
// 4. copyOf
EnumSet<Direction> se4 = EnumSet.copyOf(se3);
System.out.println(se4);
// 5.complementOf
EnumSet<Direction> se5 = EnumSet.complementOf(EnumSet.of(Direction.EAST));
System.out.println(se5);
// 6. contains
boolean isContain = se3.contains(Direction.WEST);
System.out.println(isContain);
// 7.remove
se3.remove(Direction.EAST);
System.out.println(se3);
}
}
//output
// 1. allOf
EAST
SOUTH
WEST
NORTH
// 2. noneOf
[]
// 3. of
[EAST, SOUTH]
// 4. copyOf (from 3)
[EAST, SOUTH]
// 5. complementOf (from 3)
[SOUTH, WEST, NORTH]
// 6. contains (from 3)
false
// 7. remove (from 3)
[SOUTH]
참고
자바의 정석(남궁성 저)
'프로그래밍 언어 > Java + Kotlin' 카테고리의 다른 글
[Java] 스터디 13주차: I/O (0) | 2021.09.02 |
---|---|
[Java] 스터디 12주차: 애노테이션 (0) | 2021.08.19 |
[Java] 스터디 10주차: 쓰레드 (0) | 2021.08.17 |
[Java] 스터디 9주차: 예외처리 (0) | 2021.07.29 |
[Java] 스터디 8주차: 인터페이스 (0) | 2021.07.22 |