簡體   English   中英

Java 通用類型:List 之間的區別<? extends Number>並列出<T extends Number>

[英]Java Generic type : difference between List <? extends Number> and List <T extends Number>

Java 泛型類型:有什么區別

(1) List <? extends Number>   
(2) List <T extends Number>

按照我的理解

(1) List <? extends Number> List <? extends Number>是具有超類“Number”的“未知”數據類型的只讀列表。 我們只能讀取元素但不能添加

(2) List <T extends Number>具有超類“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;
    }
}

當我嘗試將 Integer(甚至是 Number 對象)添加到 sumOfList2 中時,出現錯誤。 請解釋這里有什么問題?

基本區別是如果你使用T extends Number那么你可以參考類型T
list.add((T) new Integer(40));

好像在哪里用? extends Number ? extends Number那么你不能引用類型,但你仍然可以說:
((List<Integer>)list).add((int) s);

單獨來看,差別不大。 但是,兩個List<? extends Number> 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有一個更好的版本,但它可以正常運行。

sumOfList2TNumber一個特定子類,但它可以是它們中的任何一個。 例如T可能是BigDecimal ,並且您不能將Integer添加到List<BigDecimal>

如果您希望能夠將任何類型的數字添加到列表中,它必須是一個List<Number>

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

第一種情況非常簡單,它從T extends Number得知 T 是一個類型為 Number 類或其子類的對象。 這意味着如果我們有一個使用 T 作為 Number 類型的方法,我們可以相應地操作我們的方法,即

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

但是在這個 *Wild 字符 '?' 中 * 即使擴展了Number,我們也不知道將引用哪種類型的對象,但它可以是任何類型的對象

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)
    }

此類方法是只讀方法。

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.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM