Java中的所有通配符都可以替换为非通配符类型吗?
我找不到任何通配符不能被泛型替换的例子。 例如:
public void dummy(List<? extends MyObject> list);
等于
public <T> void dummy(List<T extends MyObject> list);
或
public <T> List<? extends T> dummy2(List<? extends T> list);
等于
public <T, U> List<U extends T> dummy(List<U extends T> list);
所以我不明白为什么创建通配符,因为泛型已经完成了这项工作。有什么想法或意见吗?
I can't find any example where wildcards can't be replaced by a generic.
For example:
public void dummy(List<? extends MyObject> list);
is equivalent to
public <T> void dummy(List<T extends MyObject> list);
or
public <T> List<? extends T> dummy2(List<? extends T> list);
is equivalent to
public <T, U> List<U extends T> dummy(List<U extends T> list);
So I don't undertand why wildcard was created as generics is already doing the job. Any ideas or comments?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不,它并不总是可以更换的。
不等于,
因为您在调用
foo()
时不知道T
(并且您无法知道List
将< 中。code>foo() 返回。同样的事情也发生在你的第二个例子 href="https://softwareengineering.stackexchange.com/questions/103710/what-has-been-learned-about-making-variance-part-of-the-type/106026#106026">使用通配符的演示可以在此(我的)答案中找到。
Nope, it is not always replaceable.
is not equivalent to
because you don't know the
T
when callingfoo()
(and you cannot know whatList<T>
willfoo()
return. The same thing happens in your second example, too.The demonstration of using wildcards can be found in this (my) answer.
一个简单的答案是,更深层次的通配符不能被类型变量替换
与
这是因为通配符捕获转换仅适用于第一级通配符。我们来谈谈这些吧。
由于广泛的捕获转换,在大多数地方,编译器将通配符视为类型变量。因此,程序员确实可以在这些地方用类型变量替换通配符,这是一种手动捕获转换。
由于编译器为捕获转换创建的类型变量不可被程序员访问,因此这具有@josefx提到的限制效果。例如,编译器将
List
对象视为List
对象;由于W
是编译器内部的,尽管它有一个方法add(W item)
,但程序员无法调用它,因为他没有W
。但是,如果程序员“手动”将通配符转换为类型变量T
,他就可以拥有类型为T
的项目并调用add(T item)就可以了。
通配符无法替换类型变量的另一个相当随机的情况:
这里,foo() 被协变返回类型覆盖,因为
List
是List。如果通配符被类型变量替换,这将不起作用。
An easy answer is that, deeper level wildcards can't be replaced by a type variable
is very different from
This is because wildcard capture conversion is only applied to 1st level wildcards. Let's talk about these.
Due to extensive capture conversion, in most places, compiler treats wildcards as if they are type variables. Therefore indeed programmer can replace wildcard with type variables in such places, a sort of manual capture conversion.
Since a type variable created by compiler for capture conversion is not accessible to programmer, this has the restricting effect mentioned by @josefx. For example, compiler treats a
List<?>
object as aList<W>
object; sinceW
is internal to compiler, although it has a methodadd(W item)
, there's no way for programmer to invoke it, because he has no item of typeW
. However, if programmer "manually" converts the wildcard to a type variableT
, he can have an item with typeT
and invokeadd(T item)
on it.Another rather random case where wildcard can't be replaced type variable:
Here, foo() is overriden with a covariant return type, since
List<Integer>
is a subtype ofList<? extends Number
. This won't work if the wildcard is replaced with type variable.您的示例存在用法差异。
返回一个列表,其中可以包含 T 的未知子类型,因此您可以从中获取类型 T 的对象,但无法添加到其中。
示例 T = Number
因此通配符可用于使某些操作无效,API 可以使用它来限制接口。
例子:
There is a usage difference for your examples.
returns a list that can contain an unknown subtype of T so you can get objects of type T out of it but can't add to it.
Example T = Number
So the wildcard can be used to make some operations invalid, this can be used by an API to restrict an interface.
Example: