Java 通用类型:List <? extends Number> 和 List <T extends Number>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18187005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 23:06:53  来源:igfitidea点击:

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

java

提问by Rakesh Soni

Java Generic type : what is the difference between

Java 泛型类型:有什么区别

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

as per my understanding

按照我的理解

(1) List <? extends Number>is the Readonly List of "unknown" data type with super class "Number". we can read the element only but can not add

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

(2) List <T extends Number>List of data type with super class "Number". we can read and addthe elements into the list

(2)List <T extends Number>具有超类“Number”的数据类型列表。我们可以读取元素并将其添加到列表中

Please see the below code example

请看下面的代码示例

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

When I am trying to add the Integer (or even Number object) into the sumOfList2 then getting the error. Please explain what is wrong here ?

当我尝试将 Integer(甚至 Number 对象)添加到 sumOfList2 中时,出现错误。请解释这里有什么问题?

采纳答案by venkat balabhadra

Basic difference is if you use T extends Numberthen you can refer to the type T:
list.add((T) new Integer(40));

基本区别是如果你使用T extends Number那么你可以参考类型T
list.add((T) new Integer(40));

Where as if you use ? extends Numberthen you can notrefer to the type, but you can still say:
((List<Integer>)list).add((int) s);

如果你使用? extends Numberthen 你不能引用类型,但你仍然可以说:
((List<Integer>)list).add((int) s);

回答by assylias

In sumOfList2, Tis a specific subclass of Number, but it can be any of them. For example Tcould be BigDecimal, and you can't add an Integerto a List<BigDecimal>.

sumOfList2,T是 的特定子类Number,但它可以是其中的任何一个。例如T可能是BigDecimal,并且您不能将 an 添加IntegerList<BigDecimal>

If you want to be able to add any types of number to the list, it has to be a List<Number>:

如果您希望能够将任何类型的数字添加到列表中,它必须是List<Number>

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

回答by Eric Jablow

In isolation, there isn't much difference. However, two instances of List<? extends Number>in a single context are completely unrelated, while two instances of List<T extends Number>in a single context refer to the same Tand the same interface.

单独来看,差别不大。但是,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);
    }
}

This method fails because ncan't be added to to, and also failed because the member types of fromand tocan be completely different.

因为此方法将失败n不能被添加到to,也失败,因为构件类型fromto可以完全不同。

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

This method compiles fine. It isn't necessary; Collectionshas a better version, but it will run without error.

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

回答by asadnwfp

The first case is very simple and its known from T extends NumberThat T is an Object which is of type Number class or its child. This means if we have a method that uses T as a type of Number we can manipulate our method accordingly i.e

第一种情况非常简单,从T extends NumberThat 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
} 

But in this *Wild character '?' * case we don't know what kind of Object is going to be referenced even though if it extends Number, but it can be any kind of Object

但是在这个 *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 '?'
}

So the only value that can be written down in such statements is null, as any type of Object can be null.

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

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

Such methods are Read Only methods.

此类方法是只读方法。

回答by Samba Namuduri

1)

1)

List <? extends Number> 

It would be appropriate to use

使用它是合适的

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

Which does not throw you an error.

这不会给您带来错误。

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

then you can add it to

然后你可以将它添加到

result = TestGen.sumOfList1(list);

2) List

2) 列表

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