来自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)
你可以添加一个Double,因为无论类型参数E是什么,它都保证是一个Number或超类型...这意味着你肯定可以转换Double为E.你将无法做到:
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.这是所有关于它的方式转换是必需的- 以泛型类型参数或从它.
Maurice Naftalin和Philip Wadler在Java Generics and Collections中解释得最好:
获取和放置原则:当您只从结构中获取值时使用扩展通配符,当您仅将值放入结构时使用超级通配符,并且当您同时获取和放置时不使用通配符.