[英]What is the difference between A<T extends B> and A<? extends B>?
I am a new java learner. 我是一名新的java学习者。 Recently I was reading Generic programming and got my self confused with this...
最近我正在阅读Generic编程,让我对此感到困惑......
A<T extends B> and A<? extends B>
First of all, those are completely different constructs used in different contexts. 首先,这些是在不同环境中使用的完全不同的结构。
A<T extends B>
is a part of generic type declaration such as A<T extends B>
是泛型类型声明的一部分,例如
public class A<T extends B> { ... }
It declares generic type A
with type parameter T
, and introduces a bound on T
, so that T
must be a subtype of B
. 它声明了类型参数为
T
泛型类型A
,并在T
上引入了一个绑定,因此T
必须是B
的子类型。
A<? extends B>
A<? extends B>
is a parameterized type with wildcard, it can be used in variable and method declarations, etc, as a normal type: A<? extends B>
是带有通配符的参数化类型,它可以在变量和方法声明等中使用,作为普通类型:
A<? extends B> a = ...;
public void foo(A<? extends B> a) { ... }
Variable declaration such as A<? extends B> a
变量声明如
A<? extends B> a
A<? extends B> a
means that type of a
is A
parameterized with some subtype of B
. A<? extends B> a
装置,该类型的a
是A
参数化的一些亚型B
。
For example, given this declaration 例如,鉴于此声明
List<? extends Number> l;
you can: 您可以:
Assign a List
of some subtype of Number
to l
: 将
Number
的某个子类型的List
分配给l
:
l = new ArrayList<Integer>();
Get an object of type Number
from that list: 从该列表中获取
Number
类型的对象:
Number n = l.get(0);
However, you can't put anything into list l
since you don't know actual type parameter of the list: 但是,由于您不知道列表的实际类型参数,因此无法将任何内容放入列表
l
:
Double d = ...;
l.add(d); // Won't compile
?
is what is called a wildcard . 就是所谓的通配符 。 It means anything that extends B.
这意味着任何延伸B.
When you write List<T extends String>
, your List
can contains only elements of type T
. 当您编写
List<T extends String>
,您的List
只能包含T
类型的元素。
When you write List<? extends String>
当你写
List<? extends String>
List<? extends String>
, your List
can contains any element that extends String
List<? extends String>
,您的List
可以包含任何extends String
元素
I hope I'm clear, since these concepts are complicated. 我希望我很清楚,因为这些概念很复杂。
(a long comment, not an answer) (长评,不是答案)
Totally different things. 完全不同的东西。 The similarity in syntax is a grave mistake made by Java.
语法的相似性是Java造成的严重错误。 And this mistake leads to a bigger mistake - many people try to understand wildcard as a type parameter (ie wildcard capture)
而这个错误会导致更大的错误 - 许多人试图将通配符理解为类型参数(即通配符捕获)
There was no such thing as A<? extends B>
没有
A<? extends B>
A<? extends B>
until Java invented it. A<? extends B>
直到Java发明它。 Until then the syntax used by researchers was A<B+>
. 在此之前,研究人员使用的语法是
A<B+>
。 Java thought that it is too mysterious for our poor programmers, so it invented that syntax A<? extends B>
Java认为这对我们糟糕的程序员来说太神秘了,所以它发明了语法
A<? extends B>
A<? extends B>
that seems to read better on first round. A<? extends B>
似乎读第一轮更好。
Well it is damn verbose and ugly. 嗯,这是多么冗长和丑陋。 If an API has a few wildcard, it looks like vomit of symbols.
如果API有一些通配符,它看起来像符号的呕吐物。
But the worse thing is the confusion it causes. 但最糟糕的是它引起的混乱。 It looks like a type parameter.
它看起来像一个类型参数。 And Java did that on purpose!
Java是故意这样做的! Java did not believe that its programmers can ever understand covariant types, so syntactically it made the convariant types look like parameterized types, to guide programmers into the erroneous way of understanding, that, admittedly, can be useful in occasions, but ultimately makes people clueless.
Java并不相信它的程序员可以理解协变类型,所以语法上它使得可变类型看起来像参数化类型,引导程序员进入错误的理解方式,不可否认,这在某些场合很有用,但最终会让人无能为力。
Generics is a complicated subject in general, and especially in Java. 泛型是一个复杂的主题,特别是在Java中。 But basically the difference is:
但基本上区别在于:
There is a specific type T, it is just limited to being B or a subclass of B, but it is a specific know type. 有一个特定的类型T,它仅限于B或B的子类,但它是一个特定的知识类型。 Any plain old generic declaration is like saying:
<T extends Object>
By saying T extends B, we are saying that T is more limited than any object, it has to specifically be a type of B. 任何普通的旧泛型声明都像是这样说:
<T extends Object>
通过说T扩展B,我们说T比任何对象都更有限,它必须特别是B的类型。
This means that the generic type is unknown, exactly, but what we can say about it is that it extends B. It may be B, it may be a subclass of B. With a wildcard and the word extends, it means that you can get B out of the object, but you cannot put anything in the object in a type safe way. 这意味着泛型类型是未知的,确切地说,但我们可以说它是扩展B.它可能是B,它可能是B的子类。使用通配符和单词extends,它意味着你可以从对象中获取B,但是你不能以类型安全的方式在对象中放置任何东西。 (? super B means the opposite - you can put something in a method parameter that is a B or a superclass of B, but you cannot be sure what the return value of a method would be.)
(?super B意味着相反 - 你可以把一些东西放在B的B或B的超类的方法参数中,但你不能确定方法的返回值是什么。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.