Java Generic类型:List <?之间的区别 extends Number>和List <T extends Number>

Rak*_*oni 23 java

Java Generic类型:有什么区别

(1) List <? extends Number>   
(2) List <T extends Number>
Run Code Online (Sandbox Code Playgroud)

按照我的理解

(1)List <? extends Number> 是具有超类"数字"的"未知"数据类型的只读列表.我们只能读取元素但不能添加

(2)List <T extends Number> 超级"数字"的数据类型列表.我们可以读取元素并将其添加到列表中

请参阅下面的代码示例

class TestGen{

    public static void main(String[] args) {
        double result = 0.0;

        List<Integer> intList = new ArrayList<Integer>();
        intList.add(10);
        intList.add(20);
        intList.add(30);

        result = TestGen.sumOfList1(intList);
        System.out.println("Result=" + result);
        result = TestGen.sumOfList2(intList);
        System.out.println("Result=" + result);
    }

    public static double sumOfList1(List<? extends Number> list) {
        double s = 0.0;
        for (Number n : list)
            s += n.doubleValue();
        return s;
    }

    public static <T extends Number> double sumOfList2(List<T> list) {
        double s = 0.0;

        // getting error while trying to add new element 
        // list<T> is not applicable for argument(Integer) : Why ?
        list.add(new Integer(40));

        for (Number n : list)
            s += n.doubleValue();

        return s;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我试图将整数(或甚至数字对象)添加到sumOfList2然后得到错误.请解释这里有什么问题?

小智 23

基本的区别是,如果你使用T extends Number那么你可以参考类型T
例如:list.add((T) new Integer(40));
如果你使用? extends Number那么你不能参考类型,但你仍然可以说((List<Integer>)list).add((int) s);


Eri*_*low 12

孤立地,没有太大区别.但是,List<? extends Number>单个上下文中的两个实例完全不相关,而单个上下文中的两个实例List<T extends Number>指的是相同T且相同的接口.

public void addAll(List<? extends Number> to, List<? extends Number> from) {
    for (Number n: from) {
        to.add(n);
    }
}
Run Code Online (Sandbox Code Playgroud)

此方法失败,因为n无法添加to,也失败,因为成员类型fromto可以完全不同.

public <T> void addAll(List<T extends Number> to, List<T extends Number> from) {
    for (T n: from) {
        to.add(n);
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法编译得很好.没有必要; Collections有一个更好的版本,但它将运行没有错误.

  • 实际上,`addAll(List &lt;TextendedNumber&gt; to,...`甚至没有编译。它必须是`&lt;TextendedNumber&gt; void addAll(List &lt;T&gt; to,...` (2认同)