[英]Java generic list return type
我在使用返回通用列表的方法時遇到了一些問題。 代碼基本上是這樣的:
public class MyClass{
private List<MyListElement> myList = new ArrayList<MyListElement>();
public <E> List<E> getGenericList(){
return new ArrayList<E>();
}
public void thisWorks(){
List<MyListElement> newList = getGenericList();
myList.addAll(newList);
}
public void thisDoesntWork(){
myList.addAll(getGenericList());
}
public void thisDoesntWorkEither(){
for(MyListElement elem : getGenericList()){
fiddle();
}
}
}
為什么thisDoesntWork()
方法不起作用,還有其他任何方法(除了做這個並不總是實用的thisWorks()
方法)?
編譯器無法推斷在thisDoesntWork()
中為泛型方法getGenericList()
的類型參數<E>
選擇的類型。
在這種情況下,您需要通過調用<MyListElement>getGenericList()
顯式聲明type參數的Type
或者,您可以更改getGenericList()
的簽名以接受Class<E>
參數。 然后你將在thisWorks()
和thisDoesntWork()
調用getGenericList(MyListElement.class)
thisDoesntWork()
。 不可否認,這有點冗長,但對於您的方法的客戶來說絕對更直觀。
我會說,作為一般規則,嘗試使泛型方法的類型參數可以從該方法的參數中推斷出來。
您可以像這樣更改thisDoesntWork()
:
public void thisDoesntWork(){ // well, it works now
myList.addAll(this.<String>getGenericList());
}
您需要告訴編譯器getGenericList()
正在處理什么類型。
泛型方法<E> getGenericsList()
的類型參數可以在調用時傳遞:
this.<String>getGenericsList()
否則編譯器會盡力從上下文中推斷出它。 將返回的對象分配給List<String>
引用時,編譯器因此推斷您將String
作為類型參數傳遞。
鑒於List API :
List<E> {
void addAll(Collection<? extends E> c);
}
編譯器似乎無法推斷出正確的類型,說實話我不知道這是因為它不夠智能,還是因為它不想通過設計承擔責任 。
我甚至做了一個測試,看看問題是否是通配符,或者addAll()
是否無法從參數化類型推斷出類型參數,但似乎沒有任何效果:
public class GenericsList {
public static void main(String[] args) {
// same signature as Java API
List<String> base = new List<String>();
base.addAll(GenericsList.getList()); // ERROR!
// addAll() doesn't use a wildcard
List2<String> base2 = new List2<String>();
base2.addAll(getList2()); // ERROR!
// what about a generic method?
addAll(base, getList()); // ERROR!
}
static <E> List<E> getList() {
return new List<E>();
}
static <E> void addAll(List<E> src, List<E> other) {}
static <E> List2<E> getList2() {
return new List2<E>();
}
static class List<E> {
void addAll(List<? extends E> other) {}
}
static class List2<E> {
void addAll(List2<E> other) {}
}
}
此代碼適合您。 getGenericList()
應該知道它返回的內容,並且應該與列表類型兼容。
您不需要將其轉換為String或其他人建議的任何其他內容,因為它會通過將其綁定到字符串類型來限制您的getGenericList方法意圖。
public class MyClass{
private List<MyListElement> myList = new ArrayList<MyListElement>();
public <E extends MyListElement> List<E> getGenericList(){
return new ArrayList<E>();
}
public void thisWorks(){
List<MyListElement> newList = getGenericList();
myList.addAll(newList);
}
public void thisDoesntWork(){
myList.addAll(getGenericList());
}
public void thisDoesntWorkEither(){
for(MyListElement elem : getGenericList()){
fiddle();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.