Enum 클래스 형을 기반으로 한 클래스형 선언(모든 상수클래스의 부모클래스 = enum)
enum vs static final
코드에 주석이 없을 경우 코드를 이해하기 어려움
int type = 1;
if(type == 1) {
System.out.println("boy");
} else {
System.out.println("girl");
}
//type에 대한 주석이나 if문 안에서 처리하는 내용에 대한 주석이 없으면 코드를 이해하기 어렵다.
해결방안 > final static을 설정한다.
private final static int BOY = 1;
private final static int GIRL = 2;
public static void main(String[] args) {
int type = 1;
if(type == BOY) {
System.out.println("boy");
} else if(type == GIRL){
System.out.println("girl");
}
}
//final static으로 설정하면 주석없이도 의미를 파악할 수 있다.
private final static int BOY = 1;
private final static int GIRL = 2;
private final static int MONDAY = 1;
private final static int TUESDAY = 2;
// 그러나 같은 상수명을 갖는 다른의미의 값이 존재하거나 다른 상수명이지만 같은 값을 가지는 경우가 있을 수 있고 에러가 발생할 수 있다.
// 각각의 상수들은 자신을 인스턴스화 한 값을 할당한다.
// BOY와 MONDAY는 서로 다른 데이터를 의미하는데 비교할 경우
if(BOY == MONDAY) {
...
}
//컴파일 에러가 발생하지 않고 런타임 단계에서 생각지 못한 문제를 발생시킬 수 있다.
해결방안 > class로 작성된 상수를 인스턴스화하여 구체화 한다.
class SEX {
public final static SEX BOY = new SEX(1);
public final static SEX GIRL = new SEX(2);
int num;
public SEX(int num) {
this.num = num;
}
}
class DAY {
public final static DAY MONDAY = new DAY();
public final static DAY TUESDAY = new DAY();
}
// 인스턴스화하면 자신의 타입으로 비교하기 때문에 컴파일시 에러를 확인할 수 있다.
int type = 1;
switch (type) {
case DAY.MONDAY:
System.out.println("월요일");
break;
case DAY.TUESDAY:
System.out.println("화요일");
break;
}
//그런데 switch문에 사용할 수 없다.
enum SEX {
BOY(1), GIRL(2);
private int sex;
SEX(int type) {
sex = type;
}
public int getSex() {
return sex;
}
}
enum DAY {
MONDAY, TUESDAY
}
SEX type = SEX.BOY;
switch (type) {
case BOY:
System.out.println("boy");
break;
case GIRL:
System.out.println("girl");
break;
}
enum과 static을 선언한 constant는 목적이 다르다.
enum은 연관된 상수들을 묶어서 추상화 시킨 거고(개념의 추상화) constant는 값의 재할당을 막기 위한 목적에 맞다.
public enum Esenmble {
//SOLO는 0, DUET은 1, ...
SOLO, DUET, TRIO, QUARTET, QUINTET,
SEXTET, SETPTET, OCTET, NONET, DECTET;
public int numberOfMusicians() {
return ordinal();
//return orinal() + 1;
}
public static void main(String[] args) {
Ensemble solo = Ensemble.SOLO;
System.out.println(solo.numberOfMusicians()); // 0 출력
}
}
//동작은 하지만 유지보수하기가 끔찍하다.
문제점이 무엇이냐?
//예시1
public enum Esenmble {
//SOLO(=1명)와 DUET(=2명)의 위치를 바꾼다면?
DUET, SOLO, TRIO, QUARTET, QUINTET,
SEXTET, SETPTET, OCTET, NONET, DECTET;
//DUET이 1로 출력돼버리는 상황 발생
//순서를 바꿔서는 안된다!
}
//예시2
public enum Esenmble {
//3중 4중주(=12명으로 구성)를 추가한다면?
DUET, SOLO, TRIO, QUARTET, QUINTET,
SEXTET, SETPTET, OCTET, NONET, DECTET, TRIPLE_QUARTET;
public int numberOfMusicians() {
return orinal() + 1;
}
public static void main(String[] args) {
Ensemble triple_quartet = Ensemble.TRIPLE_QUARTET;
System.out.println(triple_quartet.numberOfMusicians()); // 11 출력
//값을 중간에 비워둬서도 안된다.
}
}
//예시3
public enum Esenmble {
//복사중주(2*4 = 8명)를 추가한다면?
DUET, SOLO, TRIO, QUARTET, QUINTET,
SEXTET, SETPTET, DOUBLE_QUARTET,
OCTET, NONET, DECTET;
//복사중주는 8로 출력되지만 그 뒤에것들은 1씩 값이 밀려나서
//의도된 것과 다르게 numberOfMusicians 메서드가 작동
}
해결책은?
해결책 : ordinal 메서드를 사용하지말고, 인스턴스 필드를 추가하여 거기에 저장!
public enum Ensemble {
//위의 문제점(순서 변경, 중간값 비워짐, 값 중복)이 모두 해결
DUET(2), SOLO(1), TRIO(3), QUARTET(4), QUINTET(5),
SEXTET(6), SETPTET(7), DOUBLE_QUARTET(8),OCTET(8), NONET(9), DECTET(10), TRIPLE_QUARTET(12);
private final int numberOfMusicians; //각 앙상블 타입을 구성하는 뮤지션들의 숫자를 필드변수로 추가
Ensemble(int size) { this.numberOfMusicians = size } // 각 타입에 뮤지션들의 숫자를 넣도록 강제
//ordinal() 메서드를 사용하지 않고, 인스턴스 필드를 이용
public int numberOfMusicians() {
return numberOfMusicians
}
}
그럼 ordinal() 메서드는 왜 만들어놓은걸까?
Enum에 정의된 상수들은 순서와 개수가 불변이다! => 배열과 찰떡궁합
import java.util.EnumMap;
public class test03 {
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}
public static void main(String[] args) {
//EnumMap : Enum을 키로 갖는 Map의 일종
//Enum의 각 상수들은 고유한 순서를 가지고,
//그 순서와 개수가 불변이므로
//이를 바탕으로 EnumMap을 내부적으로 배열을 이용하여 구현
EnumMap<Day, String> schedule = new EnumMap<>(Day.class);
// 일정을 추가할 때 ordinal() 메서드를 사용하여 순서를 기반으로 일정을 추가
schedule.put(Day.MONDAY, "Network Study");
schedule.put(Day.TUESDAY, "LOSTARK");
schedule.put(Day.WEDNESDAY, "SSAFY PROJECT");
// Enum클래스의 values 메서드는 정의된 모든 상수를 배열로 반환(이때 ordinal메서드 이용)
// 요일을 출력할 때 ordinal() 메서드를 사용하여 순서를 표현
for (Day day : Day.values()) {
String event = schedule.get(day);
if (event != null) {
System.out.println(day + ": " + event);
}
}
}
}
🍑 서론
정수, 문자열 상수가 아닌 열거 타입(enum type)을 사용하라
정수 상수
문자열 상수
열거타입
Enum
enum vs static final
코드에 주석이 없을 경우 코드를 이해하기 어려움
해결방안 > final static을 설정한다.
🍑 본론
ordinal을 잘못 사용한 예
문제점이 무엇이냐?
해결책은?
그럼 ordinal() 메서드는 왜 만들어놓은걸까?
🍑 결론