- enum 정의하는 방법
- enum이 제공하는 메소드 (values()와 valueOf())
- java.lang.Enum
- EnumSet
열거형이란?
열거형은 서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의할 때 사용하면 유용하다.
class Card {
static final int CLOVER = 0;
static final int HEART = 1;
static final int DIAMOND = 2;
static final int SPADE = 3;
static final int TWO = 0;
static final int THREE = 1;
static final int FOUR = 2;
final int kind;
final int num;
}
------->
class Card{
enum Kind { CLOVER, HEART, DIAMOND, SPADE } //열거형 Kind를 정의
enum Value {TWO, THREE, FOUR} //열거형 Value를 정의
final Kind kind; //타입이 int가아닌 Kind임에 유의하자.
final Value value;
}
자바의 열거형은 '타입에 안전한 열거형 (typesafe enum)' 이라서 실제 값이 같아도 타입이 다르면 컴파일 에러가 발생한다.
if(Card.CLOVER == Card.TWO) //true지만 false이어야 의미상 맞음
if(Card.Kind.CLOVER == Card.Value.TWO) //컴파일에러. 값은 같지만 타입이 다름
그리고 더 중요한 것은 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일해야 하지만, 열거형 상수를 사용하면, 기존의 소스를 다시 컴파일 하지않아도 된다.
C/C++ 에서는 enum이 int값이지만, Java의 enum은 클래스기능을 갖추고 있다는 차이점도 있다.
1. enum 정의하는 방법
열거형을 정의하는 방법은 간단하다
enum 열거형이름 {상수명1, 상수명2, ...}
예를 들어 동서남북 4방향을 상수로 정의하는 열거형 Direction은 다음과 같다.
enum Direction {EAST, SOUTH, WEST, NORTH}
이 열거형에 정의된 상수를 사용하는방법은 '열거형이름.상수명' 이다. 클래스의 static 변수를 참조하는 것과 동일하다.
class Unit{
int x,y;
Direction dir;
void init(){
dir=Direction.EAST; //유닛의 방향을 EAST로 초기화
}
}
열거형 상수간의 비교에는 '=='를 사용할 수 있다. equals()가 아닌 '=='로 비교가 가능하다는 것은 그만큼 빠른 성능을 제공한다는 얘기다. 그러나 '<' , '>'와 같은 비교연산자는 사용할 수 없고 compareTo()는 사용가능하다. 앞서 배운 것과 같이 compareTo()는 두 비교대상이 같으면 0, 왼쪽이크면 양수, 오른쪽이 크면 음수를 반환한다.
if(dir == Direction.EAST){
x++;
}else if(dir > Diretion.WEST){ //에러 열거형 상수에 비교연산자 불가
..
}else if(dir.compareTo(Direction.WEST) > 0){ //compareTo()는 가능
..
}
다음과 같이 switch문의 조건식에도 열거형을 사용할 수 있다.
void move(){
switch(dir){
case EAST: x++; break; //Diretion.EAST라고 쓰면안된다.
case WEST: x--; break;
case SOUTH: y++; break;
case NORTH: y--; break;
}
}
이때 주의할 점은 case문에 열거형의 이름은 적지 않고 상수의 이름만 적여야 한다는 제약이 있다.
2. enum이 제공하는 메소드 (values()와 valueOf())
values() : 열거형의 모든 상수를 배열에 담아 반환한다. 임 메서드는 모든 열거형이 가지고 있는 것으로 컴파일러가 자동으로 추가해 준다.
for(Direction d : Direction.values()){
System.out.println(d);
}
//결과
EAST
WEST
SOUTH
NORTH
valueOf() : 지정된 열거형에서 매개변수로 주어진 String과 일치하는 열거형 상수를 반환한다.
Direction d = Direction.valueOf("WEST");
System.out.println(d);
System.out.println(Direcation.WEST == Direction.valueOf("WEST")); //ture
3. java.lang.Enum
Enum 클래스는 모든 자바 열거체의 공통된 조상 클래스이다.
메소드 설명
static E values() | 해당 열거체의 모든 상수를 저장한 배열을 생성하여 반환함. |
static E valueOf(String name) | 전달된 문자열과 일치하는 해당 열거체의 상수를 반환함. |
String name() | 해당 열거체 상수의 이름을 반환함. |
int ordinal() | 해당 열거체 상수가 열거체 정의에서 정의된 순서(0부터 시작)를 반환함. |
출처 : http://www.tcpschool.com/java/java_api_enum
코딩교육 티씨피스쿨
4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등
tcpschool.com
values() 와 valueOf()의 경우는 2번항목에 예제가 되어있다.
ordinal() 메소드
ordinal() 메소드는 해당 열거체 상수가 열거체 정의에서 정의된 순서를 반환한다.
이때 반환되는 값은 열거체 정의에서 해당 열거체 상수가 정의된 순서이며, 상숫값 자체가 아니다.
enum Rianbow {RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET}
public class EnumEx{
public static void main(String[] args){
int idx = Rainbow.YELLOW.ordinal();
System.out.println(idx);
}
}
//결과
2 // 0번부터시작하기 때문에 2번째
4. EnumSet
EnumSet은 열거형 타입으로 지정해놓은 요소들을 가장 쉽고 빠르게 배열처럼 요소들을 다룰수 있는 기능을 제공한다.
EnumSet은 기술상으로 원소갯수가 2^6 = 64개를 넘지 않을 경우에 겉은 Set기반이지만 내부적으로 long 데이터형의 비트필드를 사용하게 된다.
비트필드는 2의 제곱수들로 이루어져 메모리 공간도 적게 차지하고 속도도 빠른데 이런 원리를 기반으로 돌아가는 세트가 바로 EnumSet이다.
public class EnumSetTest{
enum Day{
SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY
}
public static void main(String[] args){
System.out.println("==================");
EnumSet es = EnumSet.allOf(Day.class);
EnumSet es2 = EnumSet.copyOf(es); //clone();
System.out.println("EnumSet Day : "+ es2);
es2 = EnumSet.noneOf(Day.class);
System.out.println("EnumSet Day : "+ es2);
es = EnumSet.of(Day.FRIDAY, Day.WEDNESDAY);
System.out.println("es : "+ es);
es2 = EnumSet.complementOf(es);
System.out.println("es2 : "+ es2);
es2 = EnumSet.range(Day.TUESDAY, Day.FRIDAY);
System.out.println("es2 : "+ es2);
}
}
//
==================
EnumSet Day: [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
EnumSet Day: []
es: [WEDNESDAY, FRIDAY]
es2: [SUNDAY, MONDAY, TUESDAY, THURSDAY, SATURDAY]
es2: [TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
allOf() 라는 메소드를 이용해서 열거형 Day에 있는 요소들을 다 가져온다. 쓰는 방식은 예제처럼 괄호안에 열거형 이름.class 를 붙인 형태를 사용한다.
이름.class인 이유는 열거형을 만들면 그와 관련된 .class가 생성된다.
noneOf() 메소드는 세트를 비우는 메소드이다.
of() 메소드는 해당 요소를 찾아서 넣으라는 것이다.
complementOf() 메소드는 괄호안의 요소들만 빼고 세트를 구성하라는 것이다. 요소 안에는 현재 WEDNESDAY, FRIDAY가 들어가 있으니 나머지 요일들이 출력된 것이다.
range() 메소드는 세트의 구간을 정해서 출력할수 있다. TUESDAY 부터 FRIDAY 까지 TUESDAY >= x >= FRIDAY 따라서 TUESDAY, WEDNESDAY, THURSDAY, FRIDAY가 출력된다.
또한 EnumSet의 명령을 접하면서 객체 생성을 안하는 이유는 EnumSet의 메소드들이 static으로 구성되어있어서 가능한 것이다. 또한, EnumSet이 추상클래스로 되어있다.
참고 문헌
JAVA의 정석
'JAVA' 카테고리의 다른 글
13주차 : I/O (0) | 2021.03.01 |
---|---|
12주차 : Annotation (애노테이션) (0) | 2021.02.07 |
10주차 : Thread (0) | 2021.01.31 |
9주차 : 예외, 에러 (0) | 2021.01.31 |
8주차 : 인터페이스 (0) | 2021.01.31 |