2014-10-17 92 views
4

如何投射Class<? extends Enum<?>>Class<T>,其中<T extends Enum<T>>?具體而言,我需要將Class<? extends Enum<?>>的實例傳遞給Enum.valueOf()方法。 http://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#valueOf(java.lang.Class,%20java.lang.String)正確投出仿製藥

這裏是我的類:

enum Foo1 implements Bar { 
    VALUE1("A"), VALUE2("B"); 

    String me; 

    Foo1(String me) { 
    this.me = me; 
    } 

    String getMe() {return me;} 
} 

enum Foo2 implements Bar { 
    V1("A"), V2("B"); 

    String me; 

    Foo2(String me) { 
    this.me = me; 
    } 

    String getMe() {return me;} 
} 

interface Bar { 
    String getMe(); 
} 

enum Z { 
    Z1(Foo1.class), Z2(Foo2.class); 
    private final Class<? extends Enum<? extends Bar>> myEnum; 
    Z(Class<? extends Enum<? extends Bar>> myEnum) { 
    this.myEnum = myEnum; 
    } 

    Class<? extends Enum<? extends Bar>> getMyEnum() { 
    return myEnum; 
    } 
} 

class X { 
    public getMe(Z z, String fooValue) { 
     Class<? extends Enum<? extends Bar>> fooEnum = z.getMyEnum(); 
     // does not compile 
     return ((Bar)Enum.valueOf(fooEnum, fooValue)).getMe(); 
    } 
} 
+0

鑄造是不安全的性質。你能告訴我們你想做什麼,爲什麼? – 2014-10-17 02:27:08

回答

0

最簡單的方式做,這是強制轉換爲原始類型Class

return ((Bar)Enum.valueOf((Class)fooEnum, fooValue)).getMe(); 

如果你不喜歡你蒙上換能的枚舉類另一個類,當你把他們在Z到保護更多的是他們的類型關係。

enum Z { 
    Z1(new Holder<>(Foo1.class)), Z2(new Holder<>(Foo2.class)); 
    private final Holder<?> myEnum; 

    Z(Holder<?> myEnum) { 
     this.myEnum = myEnum; 
    } 
    Holder<?> getMyEnumHolder() { 
     return myEnum; 
    } 

    static class Holder<T extends Enum<T> & Bar> { 
     private final Class<T> myEnum; 

     private Holder(Class<T> myEnum) { 
      this.myEnum = myEnum; 
     } 

     Class<T> getMyEnum() { 
      return myEnum; 
     } 
    } 
} 

class X { 
    public static String getMe(Z z, String fooValue) { 
     return Enum.valueOf(z.getMyEnumHolder().getMyEnum(), fooValue).getMe(); 
    } 
} 
0

這裏有一個辦法做到這一點

class X { 
    @SuppressWarnings("unchecked") 
    public <T extends Enum<T> & Bar> String getMe(Z z, String fooValue) { 
     Class<T> fooEnum = (Class<T>) z.getMyEnum(); 
     return Enum.valueOf(fooEnum, fooValue).getMe(); 
    } 
} 

對外,類型參數是無用的。在內部,它允許我們聲明既是Enum的子類型又是Bar的類型。演員到Bar也不再需要。

+0

由於特殊的枚舉規則,這與未檢查得到的一樣安全。 – Radiodef 2014-10-17 03:20:35

+0

@Radiodef我想聽聽什麼意思和爲什麼。沒有'Enum'類型,其中兩個'?'出現在聲明Class <?中擴展Enum <?擴展Bar >>'會有所不同。枚舉不是一個通用的概念。這裏沒有我能想到的投影(給出任何輸入),這會導致失敗。 – 2014-10-17 03:25:18

+0

這就是我的意思。演員絕不應該失敗。 – Radiodef 2014-10-17 03:30:10

0

基本上,根據Java的當前通用語法結構,不可能表達所需的類型關係。所以,你可以這樣做下去,或者,如果你需要的是像做

String str = someX.getMe(Z1, "VALUE1"); 

那麼你就可以拋棄枚舉並宣佈Z作爲一個普通類,它的參數。這樣你就保留了一個完整的類型參數,並可以在以後使用它。

public final class Z<E extends Enum<E> & Bar> { 
    public static final Z<Foo1> Z1 = new Z<>(Foo1.class); 
    public static final Z<Foo2> Z2 = new Z<>(Foo2.class); 

    private final Class<E> myEnumClass; 

    private Z(Class<E> myEnumClass) { 
     this.myEnumClass = myEnumClass; 
    } 

    public Class<E> getMyEnumClass() { 
     return myEnumClass; 
    } 

    /* 
    * recreate enum functionality if needed 
    */ 
} 

public <E extends Enum<E> & Bar> String getMe(Z<E> z, String fooValue) { 
    Class<E> fooEnumClass = z.getMyEnumClass(); 
    return Enum.valueOf(fooEnumClass, fooValue).getMe(); 
} 

枚舉不是很靈活。有些事情是不能做的,可能不合適。