简体   繁体   English

下限通配符

[英]Lower bound wildcards

I am trying understand the following code snippet, searched links on stackoverflow with regards to lowerbound and upperbound 我正在尝试了解以下代码片段,在stackoverflow上搜索关于lowerboundupperbound的链接

Just trying to get over the confusion in the following line , 只是想在以下几行中克服困惑,

si=s//OK why? si = s //好吗? arrays of objects can be implicitly casted to arrays of integers? 对象数组可以隐式地转换为整数数组?

 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  

Any help is appreciated 任何帮助表示赞赏

Remember that gnerics are for the benefit of the compiler not runtime information. 请记住,gnerics是为了编译器而不是运行时信息。

When you do si = s you are assigning a List of something that is a superclass of Number to a variable that can reference a List of something that is a superclass of Integer. 当你执行si = s你将一个属于Number的超类的List分配给一个变量,该变量可以引用一个Integer超类的List。

If it was a list of Number it would still be a list of Something that is a superclass of Integer. 如果它是Number的列表,它仍然是Something的一个列表,它是Integer的超类。

We know it is actually an Arraylist of Object because you have assigned so previously. 我们知道它实际上是一个对象的Arraylist,因为你之前已经分配过。

We also know that ArrayList of Object extends List of Object. 我们也知道Object的ArrayList扩展了Object的List。

List of Object is a List of something that is a superclass of Number which is why the previous assignment worked. 对象列表是一个超类数的列表,这就是前一个赋值的工作原因。

We also know that List of Object is a list of something that is a superclass of Integer but that is irrelevant to the compiler it only cares that any superclass of Number is also a superclass of Integer. 我们也知道List of Object是一个Integer超类的列表,但它与编译器无关,它只关心Number的任何超类也是Integer的超类。

I wonder if you're clear on why you would use <? super Number> 我想知道你是否清楚为什么要使用<? super Number> <? super Number> instead of <? extends Number> <? super Number>而不是<? extends Number> <? extends Number> ... <? extends Number> ...

Declaring a type with <? extends Number> 声明一个带<? extends Number>的类型 <? extends Number> guarantees to anything that takes that type that it will at least honour the contract of a Number . <? extends Number> guarantee <? extends Number>到任何采用该类型的东西,它至少会尊重Number的合约。 But a piece of code given a list of such type cannot add new members to the list. 但是给出这种类型列表的一段代码不能将新成员添加到列表中。 Consider this code: 考虑以下代码:

void appendInteger (List <? extends Number> list) {
   list.add (new Integer (3)); // Compiler error on this line
}

You could call this with appendInteger (new ArrayList <Double> ()); 你可以用appendInteger (new ArrayList <Double> ());调用它appendInteger (new ArrayList <Double> ()); Now, both Double and Integer extend Number , so the parameter will be accepted by the compiled. 现在, DoubleInteger扩展了Number ,因此编译后将接受该参数。 But you can see that if the append is allowed then the contract of the declaration in the calling code will be violated. 但是你可以看到,如果允许附加,那么违反调用代码中声明的合同。 For that reason the compiler will not allow any code that adds or replaces members in any structure declared with <? extends T> 因此,编译器不允许任何代码添加或替换使用<? extends T>声明的任何结构中的成员<? extends T> <? extends T> . <? extends T> The above method will cause a compiler error. 上述方法将导致编译器错误。

In brief, with upper-bounded wild-card types you can read the items but not place members into the structure. 简而言之,对于上限的通配符类型,您可以读取项目,但不能将成员放入结构中。

Conversely, using List <? super Number> 相反,使用List <? super Number> List <? super Number> means that the objects in the list are not more specific than Number . List <? super Number>表示列表中的对象不比Number 更具体 Consider this method: 考虑这种方法:

void getInteger (java.util.List <? extends Number> list) {
    Number n = list.get (0); // Compiler error on this line
}

The code has no idea what the type is of the elements in list . 代码不知道list元素的类型。 So the compiler will vomit with the method too. 所以编译器也会用这个方法呕吐。 You can add or replace members in list with objects of any type that is in the inheritance path of Number . 您可以使用Number的继承路径中的任何类型的对象在list添加或替换成员。 But to read the members of the list you have to treat them as type Object or use a type cast: 但要读取列表成员,您必须将它们视为Object类型或使用类型转换:

Object v = list.get (0);  // this will work
Number n = (Number) list.get (0);  // this will also work

Given this knowledge, look again at the objects involved in si = s . 有了这些知识,再看一下si = s涉及的对象。 Remember that you cannot read items from these structures, only add or replace members. 请记住,您无法从这些结构中读取项目,只能添加或替换成员。 Any object that you can place in s will also be acceptable in si . 您可以放置​​在s任何对象也可以在si接受。 So therefore it is acceptable to assign s to si . 因此,将s分配给si是可以接受的。

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

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