Java WildCards - 简单生产者消费者

时间:2013-11-15 18:25:02

标签: java generics

我目前正在实现一个需要使用通配符的问题,并使用它们创建一个非常简单的生产者/消费者类。问题在下面给出,并使用通用类型T的列表。我很困惑甚至从哪里开始这个问题。我对Wildcards非常不熟悉,并且会非常喜欢任何帮助或暗示,你们都可以提供引导我朝着正确的方向前进!我在下面列出了这个问题。

通配符。下面是一个维持库存的Shop<T>T类型的对象。有两个卖出功能:一个用于销售T类型的单个项目,另一个用于销售List<T>中的所有项目。有两种购买方法:一种是购买T类型的单一商品,另一种是一次购买n种商品,可以添加到作为购买功能参数提供的List<T>集合中。

import java.util.*;

public class Shop<T> {
    List<T> stock;

    public Shop() { 
        stock = new LinkedList<T>(); 
    }

    public T buy() {
        return stock.remove(0);
    }

    void sell(T item) {
        stock.add(item);
    }

    void buy(int n, List<T> items) {
        for (T e : stock.subList(0, n)) {
            items.add(e);
        }
        for (int i=0; i<n; ++i) stock.remove(0);
    }

    void sell(List<T> items) {
        for (T e : items) {
           stock.add(e);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在这种特殊情况下,系统会要求您修改签名void buy(int n, List<T> itmes)void sell(List<T> items),以便更好地灵活处理类型。

首先,要求您允许使用任何集合。对于此任务,如果您将两个签名都更改为接受Collection而不是List 就足够了。

第二部分是涉及通配符的地方。让我们先看看问题所在:

假设我们实例化一个Shop<Dog>并想要买一些狗。

Shop<Dog> dogShop = ...
List<Animal> myAnimals = ...
dogShop.buy(3, myAnimals); // **TYPE ERROR**

这是因为在buy我们要求Collection<Dog> 完全。相反,这应该是签名:

void buy(int n, Collection<? super T>) { /*...*/ }

这允许我们传递任何超类型T 的集合。在我们的示例中,您可以传递List<Animal>,因为AnimalDog的超类。

下一个问题是sell。同样,我们可以执行以下操作:

Shop<Animal> animalShop = ...
Set<Cat> myCats = ...
animalShop.sell(myCats); // **TYPE ERROR**

同样,我们确切地要求Collection<Animal>,所以我们无法传递一组Cat。相反,您将其签名写为:

void sell(Collection<? extends T> items) { /* ... */ }

这将接受T 的任何子类型的任何集合。在我们的示例中,Set<Cat>有效,因为Cat是[{1}}的子类型

有关详细信息和完整说明,请访问official documentation on Generic Type Wildcards