2014-10-17 17 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(); 
} 

枚举不是很灵活。有些事情是不能做的,可能不合适。