为什么这些继承的类型用作参数化类型不兼容的类型?

时间:2012-10-22 18:44:30

标签: java generics inheritance collections

我理解参数化集合,如果要使用参数化类型的子类型,则需要将集合声明为Collection<? extends Whatever>

例如:

public interface Fruit {}
public interface Banana extends Fruit {}

void thisWorksFine() {
  //Collection<Fruit> fruits;          //wrong
  Collection<? extends Fruit> fruits;  //right
  Collection<Banana> bananas = new ArrayList<>();
  fruits = bananas;
}

但如果我添加一个额外的图层,这会爆发:

public interface Box<T> {}

void thisDoesNotCompile() {
    Collection<Box<? extends Fruit>> boxes;
    Collection<Box<Banana>> bananaBoxes = new ArrayList<>();
    boxes = bananaBoxes;  // error!
}

错误:

error: incompatible types
required: Collection<Box<? extends Fruit>>
found:    Collection<Box<Banana>>

为什么这些不兼容?有没有办法让这个工作?

1 个答案:

答案 0 :(得分:4)

因为您可以向Box<Apple>添加boxes,这会违反bananaBoxes的完整性。

public interface Apple extends Fruit {}

//...

Box<Apple> apples = new Box<>(); // this is legal
Box<? extends Fruit> fruits = apples; // this is legal

Collection<Box<Banana>> bananaBoxes = new ArrayList<>(); 

Collection<Box<? extends Fruit>> boxes = bananaBoxes; //if this were legal...
boxes.add(fruits); //then this would be legal

//and this would be a type violation:
Box<Banana> bananas = bananaBoxes.iterator().next(); 

你可以改为

Collection<? extends Box<? extends Fruit>> boxes = bananaBoxes;

这是合法的,因为它可以防止上述情况。