JAVA2_06_열거형

charl hi·2021년 9월 28일
0

JAVA2

목록 보기
6/8

열거형 enum

  • 관련된 상수들을 같이 묶어놓은 것
  • 자바는 타입에 안전한 열거형을 제공한다.
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;
}

->

if(Card.CLOVER==Card.TWO)	//true

위의 경우, true지만 false여야 의미상 맞다.



아래처럼 열거형으로 표현할 수 있다.

class Card{
	enum Kind	{ CLOVER, HEART, DIAMOND, SPADE }
	//열거형 Kind
	//	상수의 값이 저절로 0, 1, 2, 3
	enum Value	{ TWO, THREE, FOUR }
	//열거형 Value
	//	상수의 값이 저절로 0, 1, 2

	final Kind	kind;	//*****타입이 int가 아닌 Kind!!!!!
	final Value	value;
}

->

if(Card.Kind.CLOVER==Card.Value.TWO)	//컴파일 에러!!! 

타입이 달라서 비교 불가 -> 컴파일 에러!!!

  • 이처럼 자바의 열거형은 값과 타입을 모두 체크한다.

  • ✨✨열거형 상수 각각 객체다!!



열거형의 정의와 사용

열거형 정의

enum 열거형이름 { 상수명1, 상수명2, ... }

예)

enum Direction { EAST, SOUTH, WEST, NORTH }

열거형 타입의 변수를 선언하고 사용하는 방법

class Unit{
	int x, y	//유닛의 위치
	Direction dir;	//열거형 인스턴스 변수를 선언
	//***이 dir은 위에서 선언한 {EAST, SOUTH...} 만 들어올 수 있다!!!

	void init(){
		dir = Direction.EAST;	//유닛의 방향을 EAST로 초기화
	}
}

열거형 상수의 비교에 ✨==, compareTo() 사용가능

📢비교연산자(>,<, ..) 사용불가!!!

-> 왜?? 객체니까!!!

if(dir==Directoin.EAST) {	//true
	x++;
} else if(dir > Direction.WEST) {	//(X) 에러!! 열거형상수에 비교연산자 사용불가
	...
} else if(dir.compareTo(Direction.WEST) > 0) {	//음수-> false
	...
}


Enum 열거형의 조상

java.lang.Enum

  • 모든 열거형은 Enum의 자손이며, 아래의 메소드를 상속받는다.

메소드

getDeclaringClass()

Class<E> getDeclaringClass()

  • 열거형의 Class객체(설계도) 반환

잘 안쓰임..

name()

String name()

  • 열거형 상수의 이름을 문자열로 반환

ordinal()

int ordinal()

  • 열거형 상수가 정의된 순서(몇번째로 상수가 선언됐는지)를 반환
  • 0~부터 시작
  • ✨순서일뿐, 상수가 갖는 값인 건 아니다!!

valueOf(enumType, name)

T valueOf(Class<T> enumType, String name)

  • 지정된 열거형에서 name과 일치하는 열거형 상수를 반환

values()

static E[] values()

  • 열거형 상수들을 배열로 반환
  • 컴파일러가 자동으로 추가
Direction[] dArr = Direction.values();

valueOf(name)

static E valueOf(String name)

  • 열거형 상수의 이름과 일치하는 열거형 상수를 반환
  • 컴파일러가 자동으로 추가
Direction d = Direction.valueOf("WEST");
//아래와 같다
Direction d = Direction.WEST

for(Direction d : dArr)		// for(Direction d : Direction.values())
	System.out.printf("%s=%d%n", d.name(), d.ordinal());	//이름, 순서 출력


열거형 상수를 얻는 방법

1. 열거형타입.상수이름

Direction d1 = Direction.EAST;
->
d1 = EAST

2. valueOf(상수이름)

Direction d2 = Direction.valueOf("EAST");
->
d2 = EAST

3. Enum.valueOf(Class<T>, 상수이름)

Direction d3 = Enum.valueOf(Directoin.class, "EAST");
->
d3 = EAST

ex12_05

//				  0		 1		2	  3
enum Direction { EAST, SOUTH, WEST, NORTH }

public class Ex12_05 {

	public static void main(String[] args) {
		//***열거형 상수를 읽어오는 방법 3가지
		Direction d1 = Direction.EAST;	//0
		Direction d2 = Direction.valueOf("WEST");	//2
		Direction d3 = Enum.valueOf(Direction.class, "EAST");	//0
		
		System.out.println("d1= "+d1);
		System.out.println("d2= "+d2);
		System.out.println("d3= "+d3);
		
		System.out.println("d1==d2 ? "+(d1==d2));
		System.out.println("d1==d3 ? "+(d1==d3));
		System.out.println("d2==d3 ? "+(d2==d3));
//		System.out.println("d2 >d3 ? "+(d2>d3));	//에러
		System.out.println("d1.equals(d2) ? "+d1.equals(d2));
		System.out.println("d1.equals(d3) ? "+d1.equals(d3));
		System.out.println("d2.equals(d3) ? "+d2.equals(d3));
		
		System.out.println("d1.compareTo(d3) ? "+d1.compareTo(d3));
		System.out.println("d1.compareTo(d2) ? "+d1.compareTo(d2));
		
		switch (d1) {
		case EAST:	//Direction.EAST 안됨. 문법틀림
			System.out.println("the directoin is EAST.");
			break;
		case SOUTH:
			System.out.println("the directoin is SOUTH.");
			break;
		case WEST:
			System.out.println("the directoin is WEST.");
			break;
		case NORTH:
			System.out.println("the directoin is NORTH.");
			break;
		default:
			System.out.println("Invaalid direction.");
			break;
		}
		
		Direction[] dArr = Direction.values();
		//열거형의 모든 상수를 배열로 반환
//		System.out.println(dArr); 로 하면 안나온다 ㅋㅋㅋ 잊지마
		for(Direction d : dArr)
			//for(Direction d : Direction.values())
			System.out.printf("%s=%d%n", d.name(), d.ordinal());
		//이름과 순서 출력
		
		
	}

}

d1= EAST
d2= WEST
d3= EAST
d1==d2 ? false
d1==d3 ? true
d2==d3 ? false
d1.equals(d2) ? false
d1.equals(d3) ? true
d2.equals(d3) ? false
d1.compareTo(d3) ? 0
d1.compareTo(d2) ? -2
the directoin is EAST.
EAST=0
SOUTH=1
WEST=2
NORTH=3


열거형에 멤버 추가하기

  • 불연속적인 열거형 상수의 경우, 원하는 값을 괄호()안에 적는다.
  • 괄호 안에 여러 개를 넣을 수 있다.
  • 이것은 ✨생성자 호출인 것
enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }
  • 괄호를 사용하려면, ✨✨iv와 생성자를 새로 추가해 줘야 한다.
enum Direction { 
	EAST(1), SOUTH(5), WEST(-1), NORTH(10); 
private final int value;	//정수를 저장할 필드(iv) 추가
Direction(int value) {
	this.value = value;	//생성자 추가
}
public int getValue() {
	return value;
}

}


- 열거형의 생성자는 묵시적으로 `private`이므로, 외부에서 객체생성 불가

```java
Direction d = new Direction(1);	//(X) 열거형의 생성자는 외부에서 호출불가


기억해야 할 것

✨✨private final iv

public getIV명()


ex12_06

enum Direction2{
	EAST(1, ">"), SOUTH(2, "V"), WEST(3, "<"), NORTH(4, "^");

	private static final Direction2[] DIR_ARR = Direction2.values();
	private final int value;
	private final String symbol;
	Direction2(int value, String symbol) {	//private 생략
		this.value = value;
		this.symbol = symbol;
	}
	
	public int getValue() {
		return value;
	}
	public String getSymbol() {
		return symbol;
	}
	
	//DIR_ARR[dir-1]의 열거형상수를 꺼내오는 메소드
	public static Direction2 of(int dir) {
		if(dir < 1 || dir > 4)	//1~4가 아니면
			throw new IllegalArgumentException("Invalid value: "+dir);
		return DIR_ARR[dir-1];	//***인덱스는 하나 작으니까!
	}
	
	//방향을 회전시키는 메소드. num의 값만큼 90도씩 시계방향으로 회전한다.
	public Direction2 rotate(int num) {
		num %= 4;	//**큰수가 나와도 되게 & 어차피 4방향이니
		
		if(num < 0)
			num += 4;	//***num이 음수일 때 시계반대방향으로 회전인데, 그게 +4한 것과 같음!
		return DIR_ARR[(value-1 + num)% 4];
		//***value가 뭔줄 알고 받는거지.....
		//아 메소드호출할때 열거형상수를 받는구나 
	}
	
	public String toString() { return name()+getSymbol();}
}



public class Ex12_06 {

	public static void main(String[] args) {
		for(Direction2 d : Direction2.values())
			System.out.printf("%s = %d%n", d.name(), d.getValue());
		//**d.getValue() 는 ordinal()과 다르다!! 값과 인덱스 다르듯이!!
		
		Direction2 d1 = Direction2.EAST;
		Direction2 d2 = Direction2.of(1);	//DIR_ARR[0]
		Direction2 d3 = Direction2.of(2);	//DIR_ARR[1]
//		Direction2 d4 = Direction2.of(6);	//예외발생
		
		System.out.printf("d1 = %s, %d%n", d1.name(), d1.getValue());
		System.out.printf("d2 = %s, %d%n", d2.name(), d2.getValue());
		System.out.printf("d3 = %s, %d%n", d3.name(), d3.getValue());
		
		//***toString()오버라이딩해서 결과가 저렇지, 안그러면 EAST(name())만 나온다!!
		System.out.println(d1);
		System.out.println(Direction2.EAST.rotate(1));
		//d1.rotate(1) 해도 됨!
		System.out.println(d1.rotate(1));
		//EAST에서 1번 시계방향으로 회전하라
		System.out.println(Direction2.EAST.rotate(2));
		System.out.println(Direction2.EAST.rotate(-1));
		System.out.println(Direction2.EAST.rotate(-2));

	}

}

EAST = 1
SOUTH = 2
WEST = 3
NORTH = 4
d1 = EAST, 1
d2 = EAST, 1
d3 = SOUTH, 2
EAST>
SOUTHV
SOUTHV
WEST<
NORTH^
WEST<



Ref

0개의 댓글