Java Generic类型:List <! - ?之间的区别extends Number - >和List <t extends =“”number =“”> </t>

时间:2013-08-12 12:28:53

标签: java

Java Generic类型:

之间有什么区别
(1) List <? extends Number>   
(2) List <T extends Number>

根据我的理解

(1)List <? extends Number>是 Readonly具有超类“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;
    }
}

当我尝试将整数(或甚至是Number对象)添加到sumOfList2中时,然后获取错误。请解释这里有什么问题?

5 个答案:

答案 0 :(得分:23)

基本区别在于,如果您使用T extends Number,则可以参考类型T
list.add((T) new Integer(40));

如果您使用? extends Number,那么您可以参考该类型,但您仍然可以说:
((List<Integer>)list).add((int) s);

答案 1 :(得分:11)

孤立地,没有太大区别。但是,单个上下文中的两个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);
    }
}

此方法失败,因为n无法添加到to,也因为fromto的成员类型完全不同而失败。

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

此方法编译良好。没有必要; Collections有一个更好的版本,但它会毫无错误地运行。

答案 2 :(得分:1)

sumOfList2中,TNumber的特定子类,但它可以是其中任何一个。{1}}。例如,T可能是BigDecimal,您无法将Integer添加到List<BigDecimal>

如果您希望能够在列表中添加任何类型的号码,则必须是List<Number>

public static double sumOfList2(List<Number> list) {...}

答案 3 :(得分:0)

1)

List <? extends Number> 

使用是合适的

List<Integer> list = Arrays.asList(0,1,2,3,4);

不会向您抛出错误。

List <Double> list = Arrays.asList(0.0,0.1,0.2,0.3,0.4);

然后您可以将其添加到

result = TestGen.sumOfList1(list);

2)列表

List<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1); Would do the job.

答案 4 :(得分:-1)

第一种情况非常简单,从T extends Number知道,T是一个类型为Number类或其子类的Object。 这意味着如果我们有一个使用T作为数字类型的方法,我们可以相应地操作我们的方法,即

<T extends Number> void myMethod ( List <T> num){
     num.add(1); // 1 is an Integer
     num.add(2.3) // 2.3 is a Double
} 

但在这个*狂野角色'?' *我们不知道哪种Object会被引用,即使它扩展了Number,但它可以是任何类型的Object

void myMethod( List <? extends Number> num){
     // num.add(1); // not a valid statement, as we dont know if '1' is of the type '?'
     // num.add(2.3)  // not a valid statement, as we dont know if '2.3' is of the type '?'
}

因此,可以在这些语句中写下的唯一值是 null ,因为任何类型的Object都可以为null。

    void myMethod( List <? extends Number> num){
      num.add(null)
    }

此类方法为只读方法。