name()
이나 기타 enum의 특정 필드값을 기준으로 다시 enum 자체를 조회할 일이 많다면 static 으로 미리 Map 을 만들어두고 Map 에서 조회하는게 낫다.public enum MyEnum { BAR, BAZ; // 외부에서는 MAP에 접근이 불가능해야한다. private static final Map<String, MyEnum> MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity())); public static MyEnum fromName(String name){ return MAP.get(name); } }
enum이 enum 생성자에서 동일 enum의 다른 값을 참조해야하는 경우가 발생할 수 있는데, 아직 초기화가 안된 다른 값을 참조하는 것은 문법적으로 불가하다. 이를 해결하는 여러가지 방법이 있다. java - Self referential enum with immutable parameters - Stack Overflow
public enum Flippable { A { public Flippable flip() { return Z; } }, B { public Flippable flip() { return Y; } }, Y { public Flippable flip() { return B; } }, Z { public Flippable flip() { return A; } }; // 아래 추상 메소드를 각 enum 에서 직접 구현한다. public abstract Flippable flip(); }
정적 초기화를 사용할 수도 있다. 그러나 이 경우에 새로운 enum이 추가될 경우 빠뜨린 값이 있을 경우가 있다. 이에 대해 정적 초기화 구문에서 validation을 해주는 코드를 넣는 것이 좋을 것 같다.
public enum Flippable { A, B, Z, Y; static { A.opposite = Z; B.opposite = Y; Y.opposite = B; Z.opposite = A; // 모두 올바르게 값 설정이 되었는지 검증 for (Flippable f : Flippable.values()) { if (f.flip().flip() != f) { throw new IllegalStateException("Flippable " + f + " inconsistent."); } } } public Flippable flip() { return opposite; } private Flippable opposite; }
정적 로딩을 하되 EnumMap을 사용한다.
public enum Flippable { A, B, Y, Z; // 외부에서 접근, 변경 불가능하도록 private으로 선언. private static final Map<Flippable, Flippable> opposites; static { opposites = new EnumMap<>(Flippable.class); opposites.put(A, Z); opposites.put(B, Y); opposites.put(Y, B); opposites.put(Z, A); // 모두 올바르게 값 설정이 되었는지 검증 for (Flippable f : Flippable.values()) { if (f.flip().flip() != f) { throw new IllegalStateException("Flippable " + f + " inconsistent."); } } } public Flippable flip() { return opposites.get(this); } }
생성자에서 enum이 아닌 enum을 나타내는 문자열을 받아서 나중에 메소드 호출시 이것을 enum 값으로 변경해주는 방법도 있다. 별로 추천하고 싶지 않음.