为什么有必要在泛型通配符中进行读取和超级写入时进行扩展?

use*_*450 3 java generics

我很难理解泛型外卡的概念.

根据我的理解<?>类型,引入未知来解决泛型中不支持的协方差,它应该适合任何类型的集合,并且<?extends T>意味着您可以拥有类型集合T或扩展的类T.<?super T>意味着您可以拥有类型集合T或超级(的)T.

如果上述错误,请纠正我.

当我尝试这样写时:

import java.util.*;

public class Gclass {
    static Gclass t;

    public void write(List< ?super String > lw){
        lw.add("b");
    }

    public void read(List< ? extends String> lr){
        String s=lr.get(2);
        System.out.println(s);
    }

    public static void main(String[] args) {
        t=new Gclass();
        List<String> l=new ArrayList<String>();
        l.add("a");
        l.add("");
        System.out.println(l);
        t.write(l);
        System.out.println(l);
        t.read(l);
        System.out.println(l);
    }
}
Run Code Online (Sandbox Code Playgroud)

它有效,但我怀疑的地方是:

  1. 根据我的理解,(extends和super)包括声明的类型,因此在这种特殊情况下,因为我List的类型String.我可以交换扩展和超级,但我得到编译错误?

  2. 如果写? super Object不起作用?它应该工作,因为它超级String?

  3. 我没有检查是否因为String无法扩展,但我认为我在这里也缺少一个概念.

我已经阅读了与此问题相关的SO的所有答案,但我仍然无法对此有充分的了解.

Ian*_*rts 5

字符串确实是一个坏的例子,因为它是一个final类,但考虑Number相反的事情.

如果一个方法接受一个类型的参数,List<? extends Number>那么你可以传递一个List<Number>或一个List<Integer>或一个List<BigDecimal>等等.在方法体内,可以把事情从列表中取出(因为你知道它们必须是实例Number)但你不能放入任何东西,因为你不知道它是否安全(例如,编译器不能让你冒险Integer进入a List<Float>).

相反,如果方法需要,List<? super Number>那么你可以传递一个List<Number>或List<Object>- 你不能从这个列表中取出任何东西,因为你不知道它是什么类型*,但是你知道放入一个肯定是安全Number 的.

*从技术上讲,你可以解决问题,但你可以指定的唯一类型是 Object