关于爪哇:阿拉里斯特超级数字与双

ArrayList <? super Number> and Double

本问题已经有最佳答案,请猛点这里访问。

从http:/ / / / / typearguments.html www.angelikalanger.com genericsfaq faqsections # faq103:

A wildcard with a lower bound looks like" ? super Type" and stands
for the family of all types that are supertypes of Type , type Type
being included. Type is called the lower bound .

那么为什么

1
2
ArrayList<? super Number> psupn1 = new ArrayList<Number>();
psupn1.add(new Double(2));

编译?

双类型数论是数论,但收藏指正.

1:编辑

1
2
3
4
5
6
7
8
    ArrayList<? super Number> pextn1 = new ArrayList<Number>();
    psupn1.add(new Integer(2));
    psupn1.add(new Double(2));
    psupn1.add(new Float(2));
    for(Number n : psupn1){ // [Invalid] Number should be change to
    // Object even if I can only add subtype of Number??

    }


你可以添加一个Double,因为无论类型参数E是什么,它都保证是Number或是一个超类型…这意味着您可以从Double转换为E。你不能这样做:

1
Number x = psupn1.get(0);

不过。

想一想,然后试着创建一个能在逻辑上打破这种局面的列表。例如,您不能使用:

1
2
3
// Invalid
ArrayList<? super Number> psupn1 = new ArrayList<Integer>();
psupn1.add(new Double(2));

因为Integer既不是Number也不是超类型——它是一个子类。你可以写:

1
2
// Valid
ArrayList<? extends Number> psupn1 = new ArrayList<Integer>();

…因为这是反过来的。这时你可以写:

1
Number x = psupn1.get(0);

因为列表中的任何元素都保证可转换为Number。这是所有需要转换的方式-到泛型类型参数或从它转换。


Maurice Naftalin和Philip Wadler在Java泛型和集合中解释得最好:

The Get and Put Principle: use an
extends wildcard when you only get
values out of a structure, use super
wildcard when you only put values into
a structure, and don't use a wildcard
when you both get and put.


List所说的是:我们保证您可以将NumberNumber的任何子类放入该List中。它不能保证你从中得到什么。考虑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void <T> addToList(List<? super T> list, T... things) {
    for (T t: things) {
        list.add(t);
    }
}

void <T> printList<List<? super T> list) {
    for (T t: list) { // doesn't compile
        System.out.println(t);
    }

    for (Object o: list) { // just fine
        System.out.println(o);
    }
}

public static void main(String[] args) {
    List<Object> objects = new ArrayList<Object>();

    // 1, 2.0f, 3.0 autoboxed to Integer, Float, Double
    addToList(objects,"a string", new Object(), 1, 2.0f, 3.0); // just fine
    printList(objects);

    List<Number> numbers = new ArrayList<Number>();
    addToList(numbers,"a string", new Object(), 1, 2.0f, 3.0); // doesn't compile
    addToList(numbers, 1, 2.0f, 3.0); // just fine
    printList(numbers);

    List<Integer> ints = new ArrayList<Integer>();
    addToList(ints, 1, 2.0f, 3.0); // doesn't compile
    addToList(ints, 1, 2, 3); // just fine
    printList(ints);
}

对于任何类型的X,只能从List中检索X,只能将X插入List中。但是您可以插入和检索X到/从List中。

在这里,您可以将任何Number插入到List的实例中,当然,您的所有示例,new Integer(2)new Double(2)等都是Number的实例,因此可以将它们放入列表中。

但是,如果你在这个列表上打电话给.get(),你就不能假定它只包含数字。看看为什么要注意这是合法的Java代码:

1
2
3
4
    List<Serializable> serializables = new ArrayList<Serializable>();
    serializables.add("You know String implements Serializable!");
    List<? super Number> list = serializables;
    Object o = list.get(0);  // Object is your best guess about the result's type

也要注意,在.get().add()中没有什么神奇的。实际上,所有这些都是因为如果检查java.util.List的定义,您可以看到.get()返回E,而add()E作为参数。