我目前正在实现一个需要使用通配符的问题,并使用它们创建一个非常简单的生产者/消费者类。问题在下面给出,并使用通用类型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);
}
}
}
答案 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>
,因为Animal
是Dog
的超类。
下一个问题是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