2016-12-15 41 views
0

我正在查看一個相對簡單的代碼塊,它碰到數據庫並將結果作爲LinkedList返回。似乎很明顯,SQL應該被注入,但後來我想到LinkedList也是不必要的依賴。java:傳遞類作爲依賴注入的參數

的簡化版本如下:

public List<String> getStrings() { 
    //Hard coded reference to LinkedList 
    List<String> tmp = new LinkedList<String>(); 
    tmp.add("foo"); 
    return tmp; 
} 

我試圖重寫它讓我在運行時指定List實現。

使用getStrings(LinkedList.class)調用getStrings(類< List> listType)給出了該方法不適用的錯誤。下面的工作確定:

public List getStrings(Class<? extends List> listType) throws InstantiationException, IllegalAccessException { 
    List tmp = listType.newInstance(); 
    tmp.add("foo"); 
    return tmp; 
} 

public void caller() throws InstantiationException, IllegalAccessException { 
    List stringList = getStrings(LinkedList.class); 
} 

但是所有引用到列表和TMP抱怨類型安全,因爲它真的應該名單< String>終止。

在getStrings()將通用工程確定:

public List<String> getStrings(Class<? extends List<String>> listType) throws InstantiationException, IllegalAccessException { 
    List<String> tmp = listType.newInstance(); 
    tmp.add("foo"); 
    return tmp; 
} 

,但更新的呼叫完全不編譯:

getStrings(LinkedList<String>.class); 

下工作,但給了我一個unchecked投警告:

getStrings((Class<? extends List<String>>) LinkedList.class); 

是否有一個正確的方式(TM)來做到這一點?

回答

2

正如您發現的那樣,運行時反射與編譯時泛型沒有很好的搭配。如果你使用的是Java 8,我會建議一個更清潔和更安全的方法:

public List<String> getStrings(Supplier<List<String>> listSupplier) { 
    List<String> tmp = listSupplier.get(); 
    tmp.add("foo"); 
    return tmp; 
} 

public void caller() { 
    List<String> stringList = getStrings(LinkedList::new); 
}