简体   繁体   English

Java通配符中的泛型

[英]Generics in java wildcards

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]");

Why we are getting compile time error? 为什么我们会出现编译时错误?

This is because of type erasure in java generics. 这是由于java泛型中的类型擦除。 You can't add new elements to listbecause its type parameter is undefined at compile time. 您不能向列表中添加新元素,因为其类型参数在编译时未定义。 The list List<? extends Number> nums 列表List<? extends Number> nums List<? extends Number> nums means that you can't call add method on it. List<? extends Number> nums意味着您不能在其上调用add方法。

List<? extends Number> List<? extends Number> means that we don't know what type is in the list, other than the fact that it is a Number . List<? extends Number>表示我们不知道列表中是什么类型,除了它是Number

In this case, it is a List<Integer> . 在这种情况下,它是List<Integer> Even when you assign it to a List<? extends Number> 即使将其分配给List<? extends Number> List<? extends Number> , it fundamentally remains a List<Integer> . List<? extends Number> ,从根本上保持List<Integer> And you can't add 3.14 to such a list. 而且您不能将3.14添加到这样的列表中。

If this were allowed, the following code would be valid: 如果允许这样做,则以下代码将有效:

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);

But ints.get(2) is not an integer, so it would throw an exception here. 但是ints.get(2)不是整数,因此会在此处引发异常。 Better to catch these kinds of issues at compile time. 最好在编译时捕获此类问题。

I think the important part here is the instantiation ( new ArrayList<Integer>() ), which clearly passes Integer to the List class. 我认为这里的重要部分是实例化( new ArrayList<Integer>() ),该实例显然将Integer传递给List类。 The left-hand side diamond notation doesn't really matter that much as long as it's compatible. 只要兼容,左侧菱形符号实际上并不重要。 Since you later on defined the generic as an upper boundary of Integer , mainly Number and its subtypes, Java is okay with that, because it still can deal with the Integers. 由于您稍后将泛型定义为Integer的上限,主要是Number及其子类型,因此Java可以接受,因为Java仍然可以处理Integers。 The object essentially still is a List<Integer> . 该对象本质上仍然是List<Integer>

This is like assigning a String to an Object. 这就像为对象分配字符串。 It will work because Object is a supertype of String . 因为ObjectString的超类型,所以它将起作用。 Here the List<? extends Number> 这里的List<? extends Number> List<? extends Number> is kind of like a supertype of List<Integer> . List<? extends Number>有点像List<Integer>的超类型。 (I know the word "supertype" is incorrect here, so feel free to correct me.) (我知道“ supertype”一词在这里是错误的,请随时纠正我。)

The instantiation with generics is sort of like an instantiation of the class itself and an object. 泛型的实例化有点像类本身和对象的实例化。 Some other languages, eg Python are using the term "metaclasses" for this sort of behavior. 一些其他语言(例如Python)正在将术语“元类”用于此类行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM