泛型的奇怪行为

时间:2014-12-13 21:56:14

标签: java generics polymorphism

我想实现一些Interpreter模式的例子。 并且在代码示例中遇到了一些麻烦。

我想使用父引用传递给子元素的方法List

enter image description here

以下是 main()

的摘录
    GoodPackage truck = new GoodPackage();
    truck.setGoodsInside(new ArrayList<Goods>());
    Bed bed = new Bed();
    GoodPackage doubleTriplePackedBed = new GoodPackage();
    doubleTriplePackedBed.setGoodsInside(Arrays.asList(new GoodPackage().setGoodsInside(Arrays.asList(bed))));


abstract class Goods {
    public abstract Integer interpret(CurrentPricesContext context);
}

class GoodPackage extends Goods {
    private List<? super Goods> goodsInside;

    @Override
    public Integer interpret(CurrentPricesContext context) {
        int totalSum = 0;
        for (Iterator<? super Goods> iter = goodsInside.iterator(); iter.hasNext(); iter.next()) {
            Goods good = (Goods) iter.next();
            totalSum += good.interpret(context);
        }
        /*for (Goods goods : goodsInside) {
            totalSum += goods.interpret(context);
        }*/
        return totalSum;
    }

    public List<? super Goods> getGoodsInside() {
        return goodsInside;
    }

    public void setGoodsInside(List<? super Goods> goodsInside) {
        this.goodsInside = goodsInside;
    }
}

class Bed extends Goods {
    @Override
    public Integer interpret(CurrentPricesContext context) {
        int price = context.getPrice(GoodsInstances.BAD);
        System.out.printf("Bad: %d%n", price);
        return price;
    }
}

问题是:

  setGoodsInside (java.util.List<? super patterns.behavioral.interpreter.Goods>)   
  can't be applicable to java.util.List<patterns.behavioral.interpreter.Bed>

我无法弄清楚我错过了什么。因为列表的类型是List<? super Goods>

有任何建议吗?

1 个答案:

答案 0 :(得分:1)

X<? super Y>X类型的对象,可能会使用Y类型的对象(即YX方法的参数类型。 X<? extends Y>X类型的对象,可以生成Y类型的对象(即Y是[{1}})方法的返回类型。

因此,X是一个列表,您可以在其中添加List<? super Goods>的任何实例,GoodsList<Goods>。这不包括List<Object>,因为您无法在其中添加List<Bed>的任何实例,只有一些(即恰好是Goods子类实例的那些实例)。

Bed是您可以从中检索List<? extends Goods>的列表,GoodsList<Goods>List<GoodPackage>。无论从列表中检索的项目是什么,它始终是List<Bed>(或其某些子类)的实例。

所以我认为你真的想使用Goods代替List<? extends Goods>

List<? super Goods>

关于这个class GoodPackage extends Goods { private List<? extends Goods> goodsInside; @Override public Integer interpret(CurrentPricesContext context) { int totalSum = 0; for (Goods goods : goodsInside) { totalSum += goods.interpret(context); } return totalSum; } public List<? extends Goods> getGoodsInside() { return goodsInside; } public void setGoodsInside(List<? extends Goods> goodsInside) { this.goodsInside = goodsInside; } } 循环:

for

它有两个问题:

  • 如果您的 for (Iterator<? super Goods> iter = goodsInside.iterator(); iter.hasNext(); iter.next()) { Goods good = (Goods) iter.next(); totalSum += good.interpret(context); } 内容不是ClassCastException(如List<Object>Goods),则会String。< / LI>
  • 您正在调用Cat方法两次。这将导致它仅解释奇数编号的项目,如果列表具有偶数个元素,则会抛出next()

不使用enhanced-for语法的等价物将是:

NoSuchElementException