2010-10-25 79 views
26

我想解決與動態枚舉查找有關的編譯錯誤(「Bound mismatch:...」)。Enum.valueOf(類<T>枚舉類型,字符串名稱)問題

基本上我想要實現這樣的事情:

String enumName = whatever.getEnumName(); 
Class<? extends Enum<?>> enumClass = whatever.getEnumClass(); 
Enum<?> enumValue = Enum.valueOf(enumClass, enumName); 

無論我做什麼,我總是與編譯錯誤告終。老實說,仿製藥和枚舉是相當mindboggling我...

我在做什麼錯在這裏?

回答

22

我認爲它不會像這樣工作,除非您有權訪問類型變量(通過類型或方法簽名)。問題是Enum.valueOf方法簽名:

public static <T extends Enum<T>> T valueOf(
    Class<T> enumType, 
    String name 
); 

有沒有辦法讓一件T沒有一個類型變量。但是你可以做這樣的,如果你願意抑制一些編譯器警告:

public enum King{ 
    ELVIS 
} 

@SuppressWarnings({ "unchecked", "rawtypes" }) 
public static void main(final String[] args){ 
    final Class<? extends Enum> enumType = King.class; 
    final Enum<?> theOneAndOnly = Enum.valueOf(enumType, "ELVIS"); 
    System.out.println(theOneAndOnly.name()); 
} 

輸出:

ELVIS

+0

的問題是關於枚舉,泛型和反思。如果忽略泛型,這有什麼意義?特別是像「Class <?extends Enum」這樣的「稀有類型」。 – 2010-10-25 12:28:04

+2

問題是a)如果沒有輔助方法或類型,它就無法工作,b)我們確信任何'類<?擴展枚舉>'也將滿足'Class >'(因爲這就是枚舉類的工作方式),即使沒有辦法檢查沒有類型變量。 '@ SuppressWarnings'是一個註釋,只有在你知道自己在做什麼時才應該使用,而且我知道。 – 2010-10-25 12:43:08

19

問題是與Class<? extends Enum<?>>。我們想要E extends Enum<E>,但我們不能得到,因爲我們有兩個不同的通配符。

因此,我們需要引入一個泛型參數,可以通過調用一個方法介紹:

enum MyEnum { 
    ME; 
} 

public class EnName { 
    public static void main(String[] args) { 
     Enum<?> value = of(MyEnum.class, "ME"); 
     System.err.println(value); 
    } 
    private static <E extends Enum<E>> E of(Class<E> clazz, String name) { 
     E value = Enum.valueOf(clazz, name); 
     return value; 
    } 
} 

但反射糞,很少你想要什麼。不要這樣做。

+1

感謝您的解釋,它對進一步瞭解正在發生的事情有很大的幫助。因爲在我的特定用例中,我沒有任何東西可以作爲泛型參數提供,所以我會去尋求seanizer的答案。 – Tom 2010-10-25 12:54:39

6

實際上有一種替代方法:你可以使用​​並且自己實現Enum.valueOf,它沒有相同類型的問題。不足之處是你找回了一個通用的Enum<?> - 但是如果你知道你進入的是什麼類型,那麼無論如何你都可以使用Enum.valueOf

private static Enum<?> findEnumValue(Class<? extends Enum<?>> enumType, String value) { 
    return Arrays.stream(enumType.getEnumConstants()) 
       .filter(e -> e.name().equals(value)) 
       .findFirst() 
       .orElse(null); 
} 

(請注意,我的版本返回null如果沒有這種持續而不是拋出IllegalArgumentException,但這是改變一件微不足道的小事。