[英]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.