아래 처럼 사용하면 위험하다. 타입 안전을 보장할 방법이 없으며 표현력도 좋지 않다.
pubic static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPLE = 1;
public enum Apple { FUJI, PIPPIN, GRANNY_SMITH }
public enum Orange { NAVEL, TEMPLE, BLOOD }
자바의 열거 타입은 완전한 형태의 클래스라서 다른 언어의 열거 타입보다 강력하다. 열거 타입은 싱글턴을 일반화한 형태라고 볼 수 있고, 컴파일 타입 안전성을 제공한다.
열거 타입 상수 각각을 특정 데이터와 연결지으려면 생성자에서 데이터를 받아 인스턴스 필드에 저장하면 된다.
public enum Planet {
MERCURY ( 3.302e +24, 2.439e6 ),
VENUS ( 4.869e + 24 , 6.05e6 ),
EARTH ( 5.975e + 24, 6.378e6 ),
MARS ( 6.419e + 23 , 3.393e6 )
private final double mass;
private final double radius;
private final double surfaceGravity;
private static final double G = 6.67300E -11;
Planet(double mass, double radius ) {
this.mass = mass;
this.radius = radius;
surfaceGravity = G * mass / ( radius * radius );
}
public double mass() { return mass; }
public double radius() { return radius; }
public double surfaceGravity { return surfaceGravity; }
}
}
toString 이 반환하는 문자열을 해당 열거 타입 상수로 변환해주는 fromString
열거 타입 상수에 연결된 값은 ordinal 메서드로 얻지말고 인스턴스 필드에 저장하자.
ordinal 메서드 : enum에서 숫서 인덱스를 반환
적당한 예시
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3)
private final int numberOfMusicians;
Ensemble(int size) { this.numberOfMusicians =size; }
public int numberOfMusicians() { return numberOfMusicians; }
}
인스턴스 필드에 저장하지 않고 ordinal 로 반환하는 코드였다면 뭔가 다른 로직을 추가할때 유지보수가 끔찍해질 수 있다.
열거 할 수 있는 타입을 한데 집합 형태로 사용한다고 해도 비트 필드를 사용할 이유는 없다.
public static final int STYLE_BOLE = 1 << 0; // 1
public static final int STYLE_ITALIC = 1 << 2 ; // 2
public void applyStyles(int styles) { ... }
비트 필드 : text.applyStyle(STYLE_BOLD | STYLE_ITALIC) ;
한마디로 비트연산자를 활용해 합집합과 교집합 같은 집합 연산을 사용할 수 있는
public class Text {
public enum Style { BOLO, ITALIC, UNDERLINE }
public void applyStyles(Set<Style> styles) {... }
}
EnumSet 클래스가 비트 필드 수준의 명료함과 성능을 제공해준다.
EnumSet : enum 인데 여러개 변수
EnumMap : Map이긴 한데 키가 Enum 인 자료구조
Map<Plant.LifeCycle, Set<Plant>> plantsLifeCycle = new EnumMap<> (Plant.LifeCycle.class );
public enum Phase {
SOLID, LIQUID, GAS;
public enum Transtition {
MELT(SOLID, LIQUID) , FREEZE( LIQUID, SOLID),
BOTL(LIQUID, GAS), CONDENST(GAS, LIQUID);
}
}
다차원 관계는 EnumMap으로 표시해라
타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 그럴 수 없다. 타입 안전 열거 패턴은 결거한 값을 그대로 가져온 다음 값을 더 추가하여 다른 목적으로 쓸수 있지만 열거 타입은 아니다.
하지만 연산 코드용 열거 타입이 임의의 인터페이스로 정의하고 열거 타입이 이 인터페이스를 구현하게 하면된다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
}
public class Sample {
@Test public static void m1();
}
애너테이션으로 할 수 있는 일을 명명 패턴으로 처리할 이유는 없다.
상위 클래스의 메서드를 재정의하려는 모든 메서드에 @Override 애너테이션을 달자.단 구체 클래스에서 상위 클래스의 추상메서드를 재정의한 경우에는 이 애너테이션을 달 필요 없다.
마커 인터페이스 : 아무 메서드도 담고 있지 않고, 단지 자신을 구현하는 클래스가 특정 속성을 가짐을 표시해주는 것
마커 인터페이스는 2가지 면에서 마커 애너테이션보다 낫다.
1) 마커 인터페이스는 이를 구현한 클래스의 인터페이스들을 구분하는 타입으로 쓸 수 있으나, 마커에네터에션은 그렇지 않다.
2) 적용 대상을 정밀하게 지정할 수 있다.
반대로 마커 애너테이션은 애너테이션 시스템의 지원을 받을 수 있다는 점에서 좋다.