2012-04-12 3 views
27

를 공유 나는 다음과 같은 열거이 : 잘 작동열거 형 정적 룩업 방법

public enum MyEnum{ 
    A(10, "First"), // 
    B(20, "Second"), // 
    C(35, "Other options"); 

    private Integer code; 
    private String description; 

    private MyEnum(Integer code, String description) { 
     this.code = code; 
     this.description = description; 
    } 

    public Integer getCode() { 
     return code; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public static MyEnum getValueOf(Integer code) { 
     for (MyEnum e : MyEnum.values()) { 
      if (e.getCode().equals(code)) { 
       return e; 
      } 
     } 
     throw new IllegalArgumentException("No enum const " + MyEnum.class.getName() + " for code \'" + code 
       + "\'"); 
    } 
} 

합니다. getValueOf -method는 외부 파트너와 통신 할 때 (선택한) 코드 만 가져 오기 때문에 존재합니다. GUI에 의미있는 구문을 표시해야하기 때문에 설명이 필요합니다.

하지만 지금은 비슷한 enum 클래스가 있습니다. 모두 자신의 코드 & 설명을 가지고 있으며 동일한 조회 기능이 필요합니다. getValueOf -method가 제네릭이어야하므로 기본적으로 동일한 방법으로 30 개 이상의 다른 enum을 지원할 필요가 없습니다.

이 문제를 해결하기 위해이 메서드를 정의하고 일부 일반적인 로직을 구현하는 추상 클래스를 만들고 싶었지만 Enum을 확장 할 수 없기 때문에 불가능합니다.

public static <T extends Enum<T>> T getValueOf(Enum<T> type, Integer code) {...} 

그러나 열거 형과 제네릭 혼란과 나는이 작업을 진행하는 방법을 이해하지 않습니다

그런 다음 나는 다음과 같은 방법으로 유틸리티 클래스를 만들기 위해 노력했다.

기본적으로 알고 싶은 것은 다음과 같습니다. 열거 형에 공통적 인 유틸리티를 정의하는 좋은 방법은 무엇입니까?

답변

22

실제 열거 형 클래스 개체를 매개 변수로 메서드에 전달해야합니다. 그런 다음 Class.getEnumConstants()을 사용하여 열거 형 값을 가져올 수 있습니다. values() 방법이기 때문에이 조금 까다 롭습니다

interface Encodable { 
    Integer getCode(); 
} 

public static <T extends Enum<T> & Encodable> T getValueOf(Class<T> enumClass, Integer code) { 
    for (T e : enumClass.getEnumConstants()) { 
     if (e.getCode().equals(code)) { 
      return e; 
     } 
    } 
    throw new IllegalArgumentException("No enum const " + enumClass.getName() + " for code \'" + code 
      + "\'"); 
} 

... 

public enum MyEnum implements Encodable { 
    ... 
} 

MyEnum e = getValueOf(MyEnum.class, 10); 
+0

참고로, 위의 경우 getCode가 null을 반환하는 경우 NPE가 throw 될 수 있습니다. null을 조건으로 'if'체크를 할 것입니다. –

+0

@ JohnB, 참으로. 나는 OP에서 코드를 복사하고 그것을 향상시키기 위해 노력하지 않았다. null 체크 대신에,'code'의 타입을'int'로 변경하여 새도우의 문제를 제거 할 수 있습니다. –

+1

나는 이것을 실제로 가져 와서 내 자신의 유틸리티 프로젝트에 포함 시켰습니다. 메소드가'public static 이되도록''Encodable' generic을 만들었습니다. getValueOf (Class enumClass, U code)'괜찮 았으면 좋겠다. –

7

: 위해, 인스턴스에 getCode()에 액세스 할 수 있도록 당신이 인터페이스를 정의하고 모든 열거 유형은 해당 인터페이스를 구현해야한다에서

공전. 실제로는 리플렉션이 필요하지만 표준 라이브러리 기능을 사용하여이를 숨기는 좋은 방법이 있습니다.

먼저 열거 유형의 모두에게 공통의 방법과 인터페이스 정의 :

public enum MyEnum implements Common {...} 

당신이 원하는 정적 방법 :

public interface Common { 
    Integer getCode(); 
    String getDescription(); 
} 

그런 다음, 모든 열거 형이 인터페이스를 구현하기를 다음과 같이 보입니다 :

public static <T extends Enum<T> & Common> T getValueOf(Class<T> type, Integer code) { 
    final EnumSet<T> values = EnumSet.allOf(type); 
    for(T e : values) { 
     if(e.getCode().equals(code)) { 
      return e; 
     } 
    } 
    throw new IllegalArgumentException("No enum const " + type.getName() + " for code \'" + code + "\'"); 
} 
+0

오, 15 초 잘 때려.내가 바꾸는 유일한 방법은 EnumSet을 만드는 대신 getEnumConstants()를 사용하는 것입니다. – Voo

+0

@Voo 예, 거의 같은 대답이지만, 많은 사람들이 즉시 알 수 있다고 생각하지 않았습니다. ^^ 음, EnumSet은 매우 효율적이며 오버 헤드는 낮아야하지만 솔직히이 방법을 알지 못했습니다. 나는 getEnumConstants()를 사용하는 단점을 보지 못했지만, 아직 그것을 사용하고있는 또 다른 대답이 있기 때문에 그대로 대답을 남겨 둘 것입니다. –

+0

당신의 코멘트는 나를 괴롭힌다. @Voo에 의해 답변이 추가 된 것을 보시겠습니까? 또는 당신이 말하는 다른 대답은 무엇입니까? –