[英]Upper-Bounded and Lower-Bounded Wildcards in return type of Java Generic method
I was trying to solve a problem where I am not able to understand part of the answer. 我试图解决一个我无法理解部分答案的问题。
Following is the class BackLister
: 以下是
BackLister
类:
public class BackLister {
// INSERT HERE
{
List<T> output = new LinkedList<T>();
for (T t : input)
output.add(0, t);
return output;
}
}
The question asks which can be inserted at // INSERT HERE
in the BackLister
class to compile and run without error? 这个问题询问哪些可以插入
// INSERT HERE
在// INSERT HERE
插入BackLister
类来编译和运行而没有错误?
Following are the options: 以下是选项:
A. public static <T> List<T> backwards(List<T> input)
B. public static <T> List<T> backwards(List<? extends T> input)
C. public static <T> List<T> backwards(List<? super T> input)
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
I understand that that A and B are correct, as for for (T t : input)
to work the elements in input
should be of type T
or subtype of T
. 据我所知,A和B是正确的,作为用于
for (T t : input)
的工作中的元素input
应类型的T
或亚型T
。
But I am not able to understand why D
and E
options are correct? 但我无法理解为什么
D
和E
选项是正确的?
I understand the following: 我理解以下内容:
public static <T> List<? extends T> backwards(List<T> input)
public static <T> List<? extends T> backwards(List<T> input)
means that the return type should be a List
of T
or subclass of T
. public static <T> List<? extends T> backwards(List<T> input)
意味着返回类型应该是一个List
的T
或子类T
。 public static <T> List<? super T> backwards(List<T> input)
public static <T> List<? super T> backwards(List<T> input)
means that the return type should be a List
of T
or superclass of T
. public static <T> List<? super T> backwards(List<T> input)
意味着返回类型应该是一个List
的T
的或超类T
。 Could somebody help me understand it? 有人可以帮我理解吗?
There is difference between each of them and I'm going to explain most of them. 每个人之间都存在差异,我将解释他们中的大多数。 Let's start with our example.
让我们从我们的例子开始。 I use this class hierarchy:
我使用这个类层次结构:
class Food {}
class Apple extends Food {}
class Orange extends Food {}
class RedApple extends Apple {}
List<Food> listFood = new ArrayList<>();
List<Apple> listApple = new ArrayList<>();
List<Orange> listOrange = new ArrayList<>();
List<RedApple> listRedApple = new ArrayList<>();
ow start with first one: 从第一个开始:
A. public static <T> List<T> backwards(List<T> input)
This method will only accept List<T>
and return List<T>
and you can not send listApple
and return listRedApple
. 此方法仅接受
List<T>
并返回List<T>
,您无法发送listApple
并返回listRedApple
。 (however your return list can contain RedApple
because it extends Apple
but type of list must be List<Apple>
and nothing else) (但是你的返回列表可以包含
RedApple
因为它扩展了Apple
但列表的类型必须是List<Apple>
而没有别的)
B. public static <T> List<T> backwards(List<? extends T> input)
You can send listRedApple
and return listApple
but you know that listRedApple
is "? extend Apple" so in the method body java recognize T as Apple. 您可以发送
listRedApple
并返回listApple
但是您知道listRedApple
是“?extend Apple”所以在方法体java中将T识别为Apple。 Then if you use can add elements in listRedApple
which sent as argument, you can add Apple
in listRedApple
which is not true!!! 然后如果你使用可以在
listRedApple
中添加作为参数发送的元素,你可以在listRedApple
中添加Apple
,这不是真的! so compiler avoid it and give compile error. 所以编译器避免它并给出编译错误。 In B you can only read elements (and get it as T) but you can not add anything to it.
在B中,您只能读取元素 (并将其作为T),但您无法添加任何内容。
C. public static <T> List<T> backwards(List<? super T> input)
You can send listApple
and then in method body you can add anything extends Apple
because compiler see T as Apple
and in a list of anything which is super of T , you can add anything extends Apple
. 您可以发送
listApple
,然后在方法体中,您可以添加任何扩展Apple
因为编译器将T视为Apple
并且在任何超级T的列表中,您可以添加任何扩展Apple
。
However this time, you can not read anything because you don't know its type except you get it as Object
. 但是这一次,你不能阅读任何东西,因为你不知道它的类型,除非你把它作为
Object
。 (It is a list of "? super T" ) (这是“超级T”的清单)
As you see here there is difference between ? 正如你在这里看到的那样有区别? super and ?
超级和? extend .
延伸 。 one of them give you write access and other give you read access.
其中一个给你写访问权限,其他给你读取权限。 This is the real use of wildcard.
这是通配符的真实用途。
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
If you send listApple
then you return List<? extends Apple>
如果你发送
listApple
然后你返回List<? extends Apple>
List<? extends Apple>
but you can's assign it to any of listFood
or listApple
or listRedApple
because List<? extends Apple>
List<? extends Apple>
但您可以将其分配给listFood
或listApple
或listRedApple
任何一个,因为List<? extends Apple>
List<? extends Apple>
maybe contain Apple
or RedApple
or something else and we can't assign it to any List<T>
because then we can add T
to that list and maybe T
and ? extends T
List<? extends Apple>
可能包含Apple
或RedApple
或其他东西,我们不能将它分配给任何List<T>
因为那样我们可以将T
添加到该列表中,也许T
和? extends T
? extends T
is not same. ? extends T
不一样。 this is same for both D
and E
. D
和E
都是一样的。 You can assign it to List<? extends Apple>
你可以将它分配给
List<? extends Apple>
List<? extends Apple>
for 'E and List<? super Apple>
List<? extends Apple>
为'E和List<? super Apple>
List<? super Apple>
for D
and send them to a method which need them as parameter. List<? super Apple>
用于D
并将它们发送到需要它们作为参数的方法。
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
Give compile errors because wildcard can not used like this. 给出编译错误,因为通配符不能像这样使用。
I hope this help you. 我希望这对你有帮助。
If something is wrong, any comment is appreciated. 如果出现问题,任何评论都表示赞赏。
Options D
and E
are valid because there exist a super-subtype relationships among generic types that allow you to define a larger set of types that the method can accept or return. 选项
D
和E
是有效的,因为泛型类型之间存在超子类型关系,允许您定义方法可以接受或返回的更大类型集。
Consequently, the following is valid (D): 因此,以下内容有效(D):
public static <T> List<? extends T> backwards(List<T> input) {
return List.of();
}
// there exist a super-subtype relationships among List<? extends Number> and List<Long>
List<? extends Number> list = backwards(List.<Long>of(1L, 2L));
because the type Long
is a member of the type family that the wildcard ? extends Number
因为
Long
类型是通配符类型族的成员? extends Number
? extends Number
denotes (the family of types that are subtypes of Number
and the type Number
itself). ? extends Number
表示(的是亚型类型的家庭Number
和类型Number
本身)。
The next code snippet is also valid (E): 下一个代码段也有效(E):
public static <T> List<? super T> backwards(List<T> input) {
return List.of();
}
List<? super Long> ints = backwards(List.<Long>of(1L, 2L));
because the type Long
is a member of the type family that the wildcard ? super Long
因为
Long
类型是通配符类型族的成员? super Long
? super Long
denotes (the family of types that are supertypes of Long
and the type Long
itself). ? super Long
表示(家庭是的超类型类型Long
和类型的Long
本身)。
So, your understanding is correct. 所以,你的理解是正确的。
Further reading . 进一步阅读 。
Below image describes the sub-typing relation in Generics: 下图描述了泛型中的子类型关系:
List<T> is a subtype of List<? super T>
Also List<T> is a subtype of List<? extends T>
This is why options D and E are correct. 这就是选项D和E正确的原因。
You can refer the page : https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html 您可以参考页面: https : //docs.oracle.com/javase/tutorial/java/generics/subtyping.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.