[英]Lower bound wildcards
我正在尝试了解以下代码片段,在stackoverflow上搜索关于lowerbound和upperbound的链接
只是想在以下几行中克服困惑,
si = s //好吗? 对象数组可以隐式地转换为整数数组?
List<? extends Number> l = new ArrayList<>();
List<? extends Integer> i = new ArrayList<>();
l = i;//OK i is a subtype of l
List<? super Number> s = new ArrayList<>();
List<? super Integer> si = new ArrayList<>();
si = new ArrayList<Integer>();//OK understand integer matches the pattern of ? super Integer
s = new ArrayList<Object>();//OK understand that object is superclass of Number
si=s//OK why? arrays of objects can be implicitly casted to arrays of integers?
//consider this
List<Integer> integers = new ArrayList<Integer>();
List<Object> objects = new ArrayList<Object>();
integers = objects; //NOT OK Type mismatch: cannot convert from List<Object> to List<Integer>
//consider this
Integer ten = 10; //integer ten
Object none = new Object();//some none
ten = none;//NOT OK none cannot be implicitly casted to ten
任何帮助表示赞赏
请记住,gnerics是为了编译器而不是运行时信息。
当你执行si = s
你将一个属于Number的超类的List分配给一个变量,该变量可以引用一个Integer超类的List。
如果它是Number的列表,它仍然是Something的一个列表,它是Integer的超类。
我们知道它实际上是一个对象的Arraylist,因为你之前已经分配过。
我们也知道Object的ArrayList扩展了Object的List。
对象列表是一个超类数的列表,这就是前一个赋值的工作原因。
我们也知道List of Object是一个Integer超类的列表,但它与编译器无关,它只关心Number的任何超类也是Integer的超类。
我想知道你是否清楚为什么要使用<? super Number>
<? super Number>
而不是<? extends Number>
<? extends Number>
...
声明一个带<? extends Number>
的类型 <? extends Number>
guarantee <? extends Number>
到任何采用该类型的东西,它至少会尊重Number
的合约。 但是给出这种类型列表的一段代码不能将新成员添加到列表中。 考虑以下代码:
void appendInteger (List <? extends Number> list) {
list.add (new Integer (3)); // Compiler error on this line
}
你可以用appendInteger (new ArrayList <Double> ());
调用它appendInteger (new ArrayList <Double> ());
现在, Double
和Integer
扩展了Number
,因此编译后将接受该参数。 但是你可以看到,如果允许附加,那么违反调用代码中声明的合同。 因此,编译器不允许任何代码添加或替换使用<? extends T>
声明的任何结构中的成员<? extends T>
<? extends T>
。 上述方法将导致编译器错误。
简而言之,对于上限的通配符类型,您可以读取项目,但不能将成员放入结构中。
相反,使用List <? super Number>
List <? super Number>
表示列表中的对象不比Number
更具体 。 考虑这种方法:
void getInteger (java.util.List <? extends Number> list) {
Number n = list.get (0); // Compiler error on this line
}
代码不知道list
元素的类型。 所以编译器也会用这个方法呕吐。 您可以使用Number
的继承路径中的任何类型的对象在list
添加或替换成员。 但要读取列表成员,您必须将它们视为Object
类型或使用类型转换:
Object v = list.get (0); // this will work
Number n = (Number) list.get (0); // this will also work
有了这些知识,再看一下si = s
涉及的对象。 请记住,您无法从这些结构中读取项目,只能添加或替换成员。 您可以放置在s
任何对象也可以在si
接受。 因此,将s
分配给si
是可以接受的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.