要求:
声明了一个基于通配符返回通用列表的方法。 声明部分正确,但方法调用失败。
class Z{/*TemplateClass*/}
public class A extends Z{}
public class B extends Z{}
测试类:
public List<? extends Z> getGenericList(boolean test){
if(test){
List<A> aList = new ArrayList<A>();
aList.add(new A());
return aList;
}
else{
List<B> bList = new ArrayList<B>();
bList.add(new B());
return bList;
}
}
这是我的要求。我需要类似下面的代码。
List<A> testAList = getGenericList(true);
List<B> testBList = getGenericList(false);
给我一个编译器错误。
类型不匹配:无法从List&lt;转换捕获#1?延伸Z>至 列表与LT; A&gt;类型不匹配:无法从List&lt;转换捕获#2?扩展 Z>列出&lt; B&gt;
我理解这背后的逻辑。如果我们传递错误并将返回的B列表存储为错误的A列表,该怎么办? 但是当我使用下面的代码时:
List<? extends Z> testList = getGenericList(true);
编译好。但它击败了我的目的。我无法访问A或B中的方法,因为testList.get(index)返回Z类型的对象,我希望得到A或B.
如果我的代码绝对错误,那么任何正确方向的指针都会受到赞赏。
答案 0 :(得分:3)
您可以转换结果,这会导致编译器错误消失,但您有一个看似代码味道的不安全转换:
List<A> testAList = (List<A>) getGenericList(true);
List<B> testBList = (List<B>)getGenericList(false);
此外,如果布尔输入不是严格要求,您也可以这样做:
public <T extends Z> List<T> getGenericList(Class<T> klass) {
List<T> list = new ArrayList<T>();
try {
list.add(klass.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return list;
}
答案 1 :(得分:1)
不会发生。您要求的类型无法在java类型系统中表达,例如List<A> + List<B>
。
最接近的是一种延续传递方式;您使用访问者界面和接受方法创建另一个抽象类,如HomogeneousListAB
。然后你可以从getGenericList返回其中一个。
abstract class HomogeneousListAB {
interface Visitor {
void ifListA( List< A > la );
void ifListB( List< B > la );
}
abstract public accept( Visitor v );
}
// inside getGenericList true branch
final List< A > laOut = // whatever
return new HomogeneousListAB() {
public accept( Visitor v ) {
v.ifListA( laOut );
}
};