ArrayList <?超级数字>和双倍

Joh*_*nGa 5 java generics

来自http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ103:

具有下限的通配符看起来像"?super Type",并且代表类型的超类型的所有类型的族,包括类型Type.类型称为下限.

所以为什么

ArrayList<? super Number> psupn1 = new ArrayList<Number>();
psupn1.add(new Double(2));
Run Code Online (Sandbox Code Playgroud)

编译?

Double不是Number的超类型,而是Number的子类......

编辑1:

    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??

    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

你可以添加一个Double,因为无论类型参数E是什么,它都保证是一个Number或超类型...这意味着你肯定可以转换DoubleE.你将无法做到:

Number x = psupn1.get(0);
Run Code Online (Sandbox Code Playgroud)

虽然.

考虑一下,并尝试创建逻辑上打破这个的列表.例如,您不能使用:

// Invalid
ArrayList<? super Number> psupn1 = new ArrayList<Integer>();
psupn1.add(new Double(2));
Run Code Online (Sandbox Code Playgroud)

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

// Valid
ArrayList<? extends Number> psupn1 = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)

......因为那是另一回事.那时你可以写:

Number x = psupn1.get(0);
Run Code Online (Sandbox Code Playgroud)

因为列表中的任何元素都保证可以转换 Number.这是所有关于它的方式转换是必需的- 泛型类型参数或它.


Jul*_*ang 5

Maurice Naftalin和Philip Wadler在Java Generics and Collections中解释得最好:

获取和放置原则:当您只从结构中获取值时使用扩展通配符,当您仅将值放入结构时使用超级通配符,并且当您同时获取和放置时不使用通配符.