Java泛型超级关键字

Java泛型超级关键字,java,generics,Java,Generics,我浏览了这些主题 然而,我似乎仍然对super关键字有点迷茫: 当我们声明这样的集合时: List<? super Number> list = null; list.add(new Integer(0)); // this compiles list.add(new Object()); // this doesn't compile 编译上述代码是不可能的(我的理智表明这是正确的行为),但基本逻辑可能证明相反: 字符串是对象,对象是数字的超类。所以字符串应该起作用。

我浏览了这些主题

然而,我似乎仍然对
super
关键字有点迷茫:

  • 当我们声明这样的集合时:

    List<? super Number> list = null;
    list.add(new Integer(0)); // this compiles
    list.add(new Object()); // this doesn't compile
    
  • 编译上述代码是不可能的(我的理智表明这是正确的行为),但基本逻辑可能证明相反:

    字符串是对象,对象是数字的超类。所以字符串应该起作用。


    我知道这很疯狂,但这不是他们不允许
    构造的原因吗?如果是,那么为什么
    对于第一部分
    列表
    适合
    列表列表
    列表
    列表中的有界通配符
    列表我有一段时间没有得到它。这里的许多答案和其他问题都具体说明了某些用法在何时何地是错误的,但并没有说明原因

    这就是我最终得到它的原因。如果我有一个将
    Number
    添加到
    列表中的函数,我可能希望添加类型为
    MySuperEfficientNumber
    的函数,这是我自己的自定义类,它实现了
    Number
    (但不是
    Integer
    的子类)。现在,调用者可能不知道关于
    MySuperEfficientNumber
    的任何信息,但只要他们知道将添加到列表中的元素视为仅是
    Number
    的特定元素,就可以了

    如果我将我的方法声明为:

    public static void addNumbersToList(List<? extends Number> numbers)
    
    显然,这是行不通的。错误将出现在
    addNumbersToList
    方法中。你会得到这样的结果:

    The method add... is not applicable for the arguments (MySuperEfficientNumber)
    
    因为
    numbers
    可以是任何特定类型的
    numbers
    ,不一定是与
    MySuperEfficientNumber
    兼容的东西。如果我翻转声明以使用
    super
    ,该方法将编译无误,但调用方的代码将失败:

    The method addNumbersToList(List<? super Number>)... is not applicable for the arguments (List<Integer>)
    

    方法addNumbersToList(List我可以给出一个非常简单的例子

    public void add(List<? super Number> list) {
    }
    

    公共void add(List这里有两个角度:当涉及有界类型时,可以将什么放入集合中,以及可以从集合中获得什么


    让我们先看一下
    ?扩展数字
    的情况。当定义了具有此类边界的集合时,我们知道的是:每个元素都有一个上界,即
    数字
    。我们不知道确切的类型(可能是
    整数/Long/etc
    ),但我们确实知道它的上界是
    数字

    因此,从这样一个集合中阅读,我们会得到一个
    数字
    。这是我们能从中获得的唯一保证类型

    禁止向这样的收藏写信。但为什么?我不是说过,当我们阅读时,我们总是会得到一个
    编号
    ,那么为什么禁止向它写信呢?这里的情况稍微复杂一些:

     List<Integer> ints = ....;
     List<? extends Number> numbers = ints;
     numbers.add(12D); // add a double in here
    
    关于
    列表
    ,我们知道它包含
    数字
    的某个超类型,例如
    对象

    从这样的列表中阅读会得到某种类型的
    X
    ,其中
    X
    将是
    Number
    的父对象。那会是什么呢?你真的不知道。它可能是理论上的
    MyNumber-extensed-Number
    ,或者更简单:一个
    对象
    。因为你不能确定,这是唯一安全的读取对象这将是所有事物的超级类型-
    对象

    有点奇怪的可能是:

    List<? super String> list = ...;
    String s = list.get(0); // fails, compiler does not care that String is final
    

    @Vuntic,很难完全清楚泛型,但我更新了我的答案,并尝试:)谢谢Colin,这让我更清楚了。这个主题需要尝试一下才能完全理解它。这是一个解释泛型的好方法,给出了所有可能的场景,但你可以添加一些颜色和粗体格式以使内容更清晰;)我无法确认你的答案是对还是错,因为它太令人困惑,并且假设了太多的知识。如果我们能理解这样的答案,就不会问这个问题@阿列克斯沃登这个答案在技术上是非常正确的,毫无疑问,如果你想要一个轻量级的解释,可能是
    public void add(List<? super Number> list) {
    }
    
    add(new LinkedList<Number>());
    
    add(new LinkedList<Object>());
    
    add(new LinkedList<Double>());
    
    add(new LinkedList<Integer>());
    
     List<Integer> ints = ....;
     List<? extends Number> numbers = ints;
     numbers.add(12D); // add a double in here
    
     List<? super Number> list = null;
     list.add(new Integer(0));
     list.add(new Object());
    
    List<? super String> list = ...;
    String s = list.get(0); // fails, compiler does not care that String is final
    
                 Some type X
                     / \
                      |
                    Number
                     / \
                      |
        Some type Y that we an put in here