[重复]

2024-05-22

有什么区别List<? super T> and List<? extends T> ?

我以前用过List<? extends T>,但它不允许我向其中添加元素list.add(e),而List<? super T> does.


extends

通配符声明List<? extends Number> foo3意味着这些都是合法的分配:

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();  // Double extends Number
  1. Reading- 鉴于上述可能的分配,您保证读取什么类型的对象List foo3:

    • 您可以阅读Number因为任何可以分配给的列表foo3包含一个Number或一个子类Number.
    • 你无法阅读Integer因为foo3可能指着一个List<Double>.
    • 你无法阅读Double因为foo3可能指着一个List<Integer>.
  2. Writing- 鉴于上述可能的分配,您可以添加什么类型的对象List foo3这将是合法的all以上可能的ArrayList作业:

    • 您无法添加Integer因为foo3可能指着一个List<Double>.
    • 你不能添加一个Double因为foo3可能指着一个List<Integer>.
    • 你不能添加一个Number因为foo3可能指着一个List<Integer>.

您无法添加任何对象List<? extends T>因为你不能保证什么样的List它确实指向,所以你不能保证该对象是允许的List。唯一的“保证”是你只能从中读取,并且你会得到一个T或子类T.

super

现在考虑List <? super T>.

通配符声明List<? super Integer> foo3意味着这些都是合法的分配:

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();   // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();   // Object is a superclass of Integer
  1. Reading- 鉴于上述可能的分配,当您读取时保证收到什么类型的对象List foo3:

    • 不保证您Integer因为foo3可能指着一个List<Number> or List<Object>.
    • 不保证您Number因为foo3可能指着一个List<Object>.
    • The only保证你会得到一个实例Object或子类Object(但你不知道是什么子类)。
  2. Writing- 鉴于上述可能的分配,您可以添加什么类型的对象List foo3这将是合法的all以上可能的ArrayList作业:

    • 您可以添加一个Integer因为一个Integer允许出现在上述任何列表中。
    • 您可以添加子类的实例Integer因为子类的实例Integer允许出现在上述任何列表中。
    • 你不能添加一个Double因为foo3可能指着一个ArrayList<Integer>.
    • 你不能添加一个Number因为foo3可能指着一个ArrayList<Integer>.
    • 您无法添加Object因为foo3可能指着一个ArrayList<Integer>.

PECS

记住PECS: “生产者延伸,消费者超”.

  • 《生产者延伸》- 如果您需要List生产T值(你想读T列表中的 s),您需要使用以下方式声明它? extends T, e.g. List<? extends Integer>。但您无法添加到此列表中。

  • 《消费超级》- 如果您需要List消费T值(你想写Ts 进入列表),你需要声明它? super T, e.g. List<? super Integer>。但不能保证您可以从此列表中读取哪种类型的对象。

  • 如果您需要读取和写入列表,则需要准确声明它,不带通配符,例如List<Integer>.

Example

Note 此示例来自 Java 泛型常见问题解答 http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ103。注意源列表的方式src(生产清单)使用extends,以及目的地列表dest(消费列表)使用super:

public class Collections { 
  public static <T> void copy(List<? super T> dest, List<? extends T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

另请参阅如何添加到列表 数据结构? https://stackoverflow.com/questions/2776975/how-can-i-add-to-list-extends-number-data-structures/2777297#2777297

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[重复] 的相关文章

随机推荐