如何将项添加到相同超类型的通用列表中?

时间:2013-08-13 14:05:42

标签: java generics

我想在我的一个服务中有一个应该返回通用列表的方法。 然后我想从其他服务向该列表添加项目。

class Fruit;
class Apple extends Fruit;

class FruitService() {
        private ArrayList<? extends Fruit> getList() {
            return new ArrayList<Apple>();
        }
}

class SomeService() {
        init() {
            fruitService.getList().add(new Apple());
        }
}

这会出现以下错误:

The method add(capture#3-of ? extends Fruit) in the type ArrayList<capture#3-of ? extends Fruit> is not applicable for the arguments (Apple)

为什么呢?我怎样才能将Apple添加到该通用列表中?

我的目标是让getList()方法不返回特定的实现。

3 个答案:

答案 0 :(得分:4)

你不能。

ArrayList<? extends Fruit> 

实际上可能是

ArrayList<Apple> 

虽然Banana,但您无法插入Banana extends Fruit。并且您无法插入Fruit,因为它必须至少包含Apple的内容。由于Java不再能够看到所需的类型,但必须保证它能够正常工作,它甚至不允许您插入Apple,尽管实际列表允许这样做。

- &GT;除了List<? extends Whatever>之外,您无法将任何插入null,因为您不知道确切的类型。 ? extends Whatever会生成Whatever的只读列表。

如果你想返回常规&amp;有用的List不会返回带有通配符类型的文件。

相反,您可以在FruitService中使用泛型,例如

class FruitService<T extends Fruit> {
    private ArrayList<T> getList() {
        return new ArrayList<T>();
    }

    public void useList(T fruit) {
        getList().add(fruit);
    }
}

class User {
    void foo() {
        FruitService<Apple> appleService = new FruitService<Apple>();
        appleService.useList(new Apple());

        FruitService<Banana> bananaService = new FruitService<Banana>();
        bananaService.useList(new Banana());
    }
}

答案 1 :(得分:2)

您可以让getList()方法返回List(或ArrayList} Fruit代替吗?这样,您就可以将Fruit的任何子类型插入List

private List<Fruit> getList() {
    return new ArrayList<Fruit>();
}

答案 2 :(得分:2)

您可以将方法设为通用 -

public <T extends Fruit> List<T> getList() {
    //....

类型变量T可以捕获实际的类型参数,因此编译器可以采用类型安全性。

此外,您可以return new ArrayList<T>();代替return new ArrayList<Apple>();