2017-01-23 209 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庫的構建器。 –