填写清单<! - ?扩展Foo - >

时间:2017-06-12 07:52:46

标签: java java-8 bounded-wildcard

拥有一组抽象对象: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);哪种方法是正确的?

3 个答案:

答案 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);

这是确保列表元素属于调用者指定类型的唯一方法。另一方面,这要求TFoo的子类型已过时。

您可以将<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;
}