1

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

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() 方法不返回特定的实现。

4

3 回答 3

4

你不能。

ArrayList<? extends Fruit> 

实际上可能是

ArrayList<Apple> 

您不能在其中插入Banana虽然Banana extends Fruit。而且您不能插入 aFruit因为它至少必须是 extends Apple。而且由于 Java 不能再看到所需的类型,但必须保证它会工作,它甚至不允许您插入一个,Apple尽管实际列表允许这样做。

-> 你不能插入任何东西List<? extends Whatever>null因为你不知道确切的类型。? extends Whatever生成 的只读列表Whatever

如果您想返回常规且有用的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());
    }
}
于 2013-08-13T14:09:30.890 回答
2

你可以让你的getList()方法返回一个List(或ArrayListFruit代替吗?这样,您可以将任何子类型Fruit插入List.

private List<Fruit> getList() {
    return new ArrayList<Fruit>();
}
于 2013-08-13T14:11:01.750 回答
2

您可以使该方法通用-

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

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

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

于 2013-08-13T14:12:37.293 回答