泛型中extends和super的区别

extends

通配符式声明 List foo3 意味着以下每一条皆为合法语句:

List foo3 = new ArrayList();  // Number "extends" Number (in this context)
List foo3 = new ArrayList(); // Integer extends Number
List foo3 = new ArrayList();  // Double extends Number
  1. - 若有以上声明,则对List foo3进行读操作时会出现以下情形:
    • 可以读取Number类型的数据,因为可以赋予foos的列表均包含Number类型或其子类型的数据。
    • 无法读取Integer类型的数据,因为foo3可能指向List类型的数据。
    • 无法读取Double类型的数据,因为foo3可能指向List类型的数据。
  2. - 若有以上声明,则对List foo3进行写操作(add)时会出现以下情形:
    • 无法增添Integer类型的数据,因为foo3可能指向List类型的数据。
    • 无法增添Double类型的数据,因为foo3可能指向List类型的数据。
    • 无法增添Number类型的数据,因为foo3可能指向List类型的数据。

无法向List添加任何对象,因为无法保证变量具体指向的是什么类型的List,从而无法保证目标List允许添加何种类型的对象。唯一能保证的是可以从中读出一个T类型或其子类型的数据。

super

List .

通配符式声明 List foo3 意味着以下每一条皆为合法语句:

List foo3 = new ArrayList();  // Integer is a "superclass" of Integer (in this context)
List foo3 = new ArrayList();   // Number is a superclass of Integer
List foo3 = new ArrayList();   // Object is a superclass of Integer

  1. - 若有以上声明,则对List foo3进行读操作时会出现以下情形:
    • 无法读取Integer类型的数据,因为foo3可能指向ListList类型的数据。
    • 无法读取Number类型的数据,因为foo3可能指向List类型的数据。
    • 只能读取Object类型或Object子类型的数据(但无法确定是那个子类)。
    • - 若有以上声明,则对List foo3进行写操作(add)时会出现以下情形:
      • 可以增添Integer类型的数据,因为示例代码中的所有list均允许增添Integer类型的数据。
      • 可以增添Integer子类型的数据,因为示例代码中的所有list均允许增添Integer子类型的数据。
      • 无法增添Double类型的数据,因为foo3可能指向ArrayList类型的数据。
      • 无法增添Number类型的数据,因为foo3可能指向ArrayList类型的数据。
      • 无法增添Object类型的数据,因为foo3可能指向ArrayList类型的数据。
    • PECS

      记住一个口诀: "Producer Extends, Consumer Super"(PECS).

      • "Producer Extends" - 如果一个List需要生产T类型的数据(你想要从list中读取T类型数据),你需要将其声明成? extends T, e.g. List。但你无法向其中增添数据。
      • "Consumer Super" - 如果你需要一个消费T类型数据的list(向其中增添T类型数据),你需要将其声明成? super T, e.g. List。但是你将不知道会从中读取到何种类型的数据。
      • 如果你需要从对List进行读和写操作,则不要使用通配符式的声明方式,e.g. List

      ===> 翻译于StackOverflow

      你可能感兴趣的:(泛型中extends和super的区别)