拥有一组抽象对象:Set<Foo> foes;
我想要一个像这样的方法:
List<? extends Foo> getFoesByType(TypeEnum type);
我试过了:
List<? extends Foo> result = new ArrayList<>();
for(Foo f : foes) {
if(f.getType() == type) {
switch(type) {
case TYPE1:
f = (FooType1) f;
break;
case TYPE2:
/*...*/
}
result.add(f);
/*The method add(capture#1-of ?) in the type
List<capture#1-of ?> is not applicable for the arguments (Foo)*/
}
}
return result;
但是我收到了错误。
我希望能够做到这一点:List<FooType1> foesType1 = getFooesByType(TypeEnum.TYPE1);
哪种方法是正确的?
答案 0 :(得分:6)
唯一安全的方法是添加Class
参数以支持运行时的类型检查:
private <T extends Foo> List<T> getFooesByType(EnumType type, Class<T> type) {
List<T> result = new ArrayList<>();
for(Foo f : foes) {
if(f.getType() == type) {
switch(type) {
case TYPE1:
// do something, cast is not necessary
break;
case TYPE2:
/*...*/
}
result.add(type.cast(f)); // safe cast
}
}
return result;
}
被称为
List<FooType1> foesType1 = getFooesByType(TypeEnum.TYPE1, FooType1.class);
这是确保列表元素属于调用者指定类型的唯一方法。另一方面,这要求T
是Foo
的子类型已过时。
您可以将<T extends Foo>
更改为<T>
,以提高方法的灵活性,
例如List<Object> list = getFooesByType(TYPE1, Object.class);
也是合法的。
答案 1 :(得分:3)
您需要使您的方法具有通用性:
private <T extends Foo> List<T> getFooesByType(EnumType type) {
List<T> result = new ArrayList<>();
for(Foo f : foes) {
if(f.getType() == type) {
switch(type) {
case TYPE1:
// do something, cast is not necessary
break;
case TYPE2:
/*...*/
}
result.add((T) f); // cast here
}
}
return result;
}
答案 2 :(得分:0)
你不能这样做。 ? extends Foo
表示可能有Foo
级的任何孩子。您不知道究竟是什么,以及为什么您无法添加到List<? extends Foo>
。
但您可以创建数组列表并将其分配给List然后返回。
List<? extends Foo> getFoesByType(TypeEnum type) {
List<Foo> result = new ArrayList<>();
// add something to result list
return result;
}