2012-10-22 41 views
1

我与参数的集合明白,如果你要使用参数化类型的子类型,你需要声明的集合作为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>> 

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

回答

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; 

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