填写列表<?扩展 Foo>
Filling a List<? extends Foo>
拥有一组抽象对象: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);
哪种方法是正确的?
你不能这样做。 ? extends Foo
表示可能有 Foo
class 中的任意 child。你不知道它到底是什么,这就是你不能添加到 List<? extends Foo>
.
的原因
但您可以创建数组列表并将其分配给 List,然后 return。
List<? extends Foo> getFoesByType(TypeEnum type) {
List<Foo> result = new ArrayList<>();
// add something to result list
return result;
}
您需要使您的方法通用:
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;
}
唯一安全的方法是添加一个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);
也是合法的。
拥有一组抽象对象: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);
哪种方法是正确的?
你不能这样做。 ? extends Foo
表示可能有 Foo
class 中的任意 child。你不知道它到底是什么,这就是你不能添加到 List<? extends Foo>
.
但您可以创建数组列表并将其分配给 List,然后 return。
List<? extends Foo> getFoesByType(TypeEnum type) {
List<Foo> result = new ArrayList<>();
// add something to result list
return result;
}
您需要使您的方法通用:
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;
}
唯一安全的方法是添加一个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);
也是合法的。