2015-04-17 74 views
1

參考下面的代碼片段,我有一個接口Splitter,其中接受通用類型參數TV。有一個實現是CompanySplitterImpl。可能有很多這樣的實現。java中通用類型實現的返回類型應該是什麼

public interface Splitter<T, V> { 
    V[] split(T arg); 
} 

public class CompanySplitterImpl 
implements Splitter<Company, Department> { 

    @Override 
    public Department[] split(Company comp) { 

     return comp.getDepartment(); 
    } 
} 

我想寫返回基於在工廠方法傳遞的一個關鍵參數值不同的實現工廠方法。

// Factory method to return different Implementation of Splitter 
// (Is Splitter return type correct?) 
public static Splitter getSplitter(String key) { 

    return new CompanySplitterImpl(); // Is this correct? 
} 

我的問題是什麼是返回不同實施Splitter<K, V>實例的正確方式?

// Client to call factory method... 
// Not sure what will be type argument for Splitter type 
Splitter<?> split = getSplitter("dummyKey"); 

在客戶端,什麼是Splitter類型的類型參數?

+1

你連接到使用'String'作爲一個關鍵的想法?請注意'Splitter'是[原始類型](http://stackoverflow.com/q/2770321/2891664),可能不是一個好主意。你正在失去安全性。相關:[*「避免在具有多個值類型的地圖中進行未經檢查的賦值?」](http://stackoverflow.com/a/22468599/2891664) – Radiodef

+0

也應該儘量避免使用泛型類型的數組 - 使用'列表'而不是。原因很複雜,但基本上仿製藥可以很容易地避免泛型的類型安全益處。 – yshavit

+0

'CompanySplitterImpl'是一個'Splitter ',就像您定義的一樣。 – Bubletan

回答

5

Splitter是原始類型。你不應該使用原始類型。由於密鑰(String)沒有攜帶類型信息,因此無法從傳遞給getSplitter的參數中推斷出類型參數。因此,避免原始類型的唯一方法是使返回類型爲Splitter<?, ?>

這是醜陋和強制方法的調用者投:

​​

這樣做的更好的方法是使用攜帶類型信息的密鑰,通常的方式做到這一點是使用Class<T>對象。

public static <T, V> Splitter<T, V> getSplitter(Class<T> key1, Class<V> key2) { 

    if (key1 == Company.class && key2 == Department.class) 
     return (Splitter<T, V>) new CompanySplitterImpl(); 

    // more cases 
} 

然後調用者可以這樣做:

Splitter<Company, Department> split = getSplitter(Company.class, Department.class); 
+0

是否可以通過從某個外部配置文件中讀取關鍵信息(Company.class和Department.class)來動態傳遞它? – Vinit89