我有一个带有上限泛型的列表.
List<? extends Number> l = new ArrayList<>();
l.add(new Integer(3)); //ERROR
l.add(new Double(3.3)); // ERROR
Run Code Online (Sandbox Code Playgroud)
我不明白这个问题,因为Integer和Double扩展了Number.
Tob*_*obb 24
List<? extends Number>
并不意味着"一个可以容纳子类的所有对象的列表Number
",它意味着"一个参数化为一个扩展的具体类的列表Number
".它不是你定义的列表本身的内容,它是分配给变量的实际列表对象的参数化类型(男孩,这比理解它更难解释:))
所以,你可以这样做:
List<? extends Number> l = new ArrayList<Integer>();
List<? extends Number> l = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)
如果您想要一个能够容纳类Number或其子类的任何对象的列表,请执行以下操作:
List<Number> l = new ArrayList<>();
l.add(new Integer(33));
l.add(new Double(33.3d));
Run Code Online (Sandbox Code Playgroud)
(插入的值的装箱是不必要的,但为了清楚起见..)
上界和无界通配符集合是不可变的。
例如,您不能执行以下操作:
List<? extends Number> myList = new ArrayList<Integer>();
myList.add(new Integer(3)); //will not compile
Run Code Online (Sandbox Code Playgroud)
编译失败,因为Java List<? extends Number>
在编译时不知道List的类型。
所以上面的示例中,在编译时, myList
可能是List<Double>
或List<Integer>
或List
的任何亚类的Number
。而且由于不能将a添加Double
到a List<Integer>
或反之亦然,因此编译失败。
小智 6
上限泛型的问题是编译器不知道将使用的确切类型,例如:
List<? extends Number> upperBounded = new ArrayList<Integer>();
upperBounded = new ArrayList<Double>();
Run Code Online (Sandbox Code Playgroud)
upperBounded
可以是整数列表,也可以是双精度列表或任何其他 Number 后代。现在想象一下,如果 Java 允许我们将 Number 的任何子类添加到该 List 中,将会发生什么。
List<? extends Number> upperBounded = new ArrayList<Integer>();
upperBounded.add(1.0); // compile-time error
Run Code Online (Sandbox Code Playgroud)
好在 Java 阻止我们这样做,因为这会引入很多错误。
这同样适用于无界泛型类型。
现在下限泛型怎么样?
List<? super Integer> lowerBounded = new ArrayList<Integer>();
lowerBounded.add(0);
Run Code Online (Sandbox Code Playgroud)
这是完全可以的,因为我们可以安全地假设我们可以将 Integers 添加到 Integer 超类的任何 List 中,并且这不会导致不一致,例如:
List<? super Integer> lowerBounded = new ArrayList<Number>();
lowerBounded.add(0);
Run Code Online (Sandbox Code Playgroud)
这里我们有一个允许整数列表或整数超类型之一的引用。Numbers 的 ArrayList 符合该定义,因此我们可以将其分配给该引用。然后我们可以向这个列表添加一个整数,这也很好,因为数字列表可以包含一个整数(因为整数是一个数字)。
这可能会令人惊讶,但您不能将任何不可分配给 Integer 的内容添加到此列表中,原因与我上面针对下限泛型所解释的原因相同。
List<? super Integer> lowerBounded = new ArrayList<Number>();
lowerBounded.add(1.0); // compile-time error
Run Code Online (Sandbox Code Playgroud)
由于编译器不知道将使用哪种确切类型的 List,因此它不允许我们添加任何可能违反泛型给出的承诺的内容。
希望有帮助。
因为List<? extends Number>
意味着您的变量持有一个具有扩展的具体(但未知!)类型参数l
的类型值。List
Number
您只能添加null
,因为l
可以保存List<MyClass>
例如,MyClass
扩展的类在哪里Number
,但 或Integer
,也不Double
能将值转换为MyClass
。