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

标签 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>>

为什么这些不兼容?有什么方法可以让它发挥作用吗?

最佳答案

因为你可以添加一个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;

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

关于java - 为什么这些继承类型被用作参数化类型不兼容类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13017705/

相关文章:

java - 尝试删除大于我的目标数字的数字

java - 使用 JSON Sanitizer 清理来自 Spring MVC Controller 的响应 JSON?

java - 无法创建 Map.Entry 类型的泛型类

java - 将泛型参数与静态compareObject方法结合使用

c++ - 如何将 shared_ptr<A> 转换为 shared_ptr<B>,其中 B 派生自 A?

Java RMI : Rejecting requests when saturation is reached

java - 多个文件未在 Play 框架中上传

java - 学习 Java 泛型的资源?

c# - 覆盖/隐藏显式实现的接口(interface)方法

使用私有(private) Setter 进行 Java 继承