2017-01-23 153 views
0

想象一下,你有这样的情况:Java的泛型返回动态类型

// Marker 
interface Type {} 

interface CustomType extends Type { 
    int getSomething(); 
    int getAnotherThing(); 
} 

class CustomTypeImpl implements CustomType { 
    public int getSomething() { 
     return 1; 
    } 
    public int getAnotherThing() { 
     return 2; 
    } 
} 

在另一类,我想有这样一个通用的方法:

public <T extends CustomType> T getFromInterface(Class<T> clazz) 

返回的实现我输入参数。例如,我想调用如下的方法:SomeInstanceOfClass.getFromInterface(CustomType.class),它返回一个CustomTypeImpl的实例。

@ EDIT:我忘了提及我有权访问一个方法,该方法存储所有可用作方法参数的接口。

此方法的签名是:public Set<? extends Class<? extends Type>> allTypes()

如何管理做到这一点吗?

+0

如果接口有两个实现呢?如果它从来不这样做,那么接口的意义何在? –

+0

实际上,我有一个标记接口,允许我的对象具有通用类型。情况就像这样:interface Type {// marker} interface CustomType extends Type {// look above}和我的实现。实际上,我有扩展Type的其他接口,然后我为每个扩展Type的接口实现了一个实现。 –

+3

答案可能会解决您的问题,但我认为无论您的问题是什么,都可能有更好的解决方案。 –

回答

2

您可以使用反射并使用类对象创建一个新实例。关于什么类实现某个接口的信息可以存储在某个映射中。

private static final Map<Class<?>, Class<?>> interfaceToImplementationMap = new HashMap<Class<?>, Class<?>>() {{ 
    put(CustomType.class, CustomTypeImpl.class); 
}}; 

public static void main(String[] args) throws InstantiationException, IllegalAccessException { 
    CustomType instance = getFromInterface(CustomType.class); 
    System.out.println(instance); 
} 

public static <T> T getFromInterface(Class<T> clazz) throws IllegalAccessException, InstantiationException { 
    return clazz.cast(interfaceToImplementationMap.get(clazz).newInstance()); 
} 
+1

有很多网页解释了为什么你不应该使用“双括号初始化”。改为使用一个静态初始化块。除此之外,很好的答案。 – VGR

+0

这是真的。我完全同意上述评论。我还建议查看一下com.google.common.collect.ImmutableMap及其静态方法 - 来自guava库的构建器。 –