java通配符中的泛型

时间:2017-04-11 05:43:09

标签: java

List<Integer> ints = new ArrayList<Integer>();
 ints.add(1); ints.add(2);
 List<? extends Number> nums = ints;
 nums.add(3.14);   // compile-time error
assertints.toString().equals("[1, 2, 3.14]");

为什么我们收到编译时错误?

3 个答案:

答案 0 :(得分:1)

这是因为java泛型中的类型擦除。 您无法向list添加新元素,因为它的类型参数在编译时未定义。 列表List<? extends Number> nums表示您无法在其上调用add方法。

答案 1 :(得分:1)

List<? extends Number>表示我们不知道列表中的类型,只是它是Number

在这种情况下,它是List<Integer>。即使您将其分配给List<? extends Number>,它也基本上仍为List<Integer>。并且你不能将3.14添加到这样的列表中。

如果允许,则以下代码有效:

List<Integer> ints = new ArrayList<Integer>();
ints.add(1); ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14);
Integer third = ints.get(2);

但是ints.get(2)不是整数,所以它会抛出异常。最好在编译时捕获这些问题。

答案 2 :(得分:0)

我认为这里的重要部分是实例化(new ArrayList<Integer>()),它明确地将Integer传递给List类。左手边的钻石符号并不重要,只要它兼容即可。由于您后来将泛型定义为Integer的上边界,主要是Number及其子类型,因此Java可以处理它,因为它仍然可以处理整数。该对象基本上仍然是List<Integer>

这就像将一个String赋给一个Object。它会起作用,因为ObjectString的超类型。这里List<? extends Number>有点像List<Integer>的超类型。 (我知道“超级型”这个词在这里是不正确的,所以请随意纠正我。)

使用泛型的实例化有点像类本身和对象的实例化。其他一些语言,例如Python正在使用术语“元类”来表达这种行为。

相关问题