无界通配符之间是否存在差异,例如<?>
和有界通配符,其边界为Object
,例如<? extends Object>
?
我记得在某处读过仿制药的早期草稿有所不同,但是找不到那个来源了。
答案 0 :(得分:32)
从大多数人的实际角度来看,<? extends Object>
与<?>
相同,就像所有人在此提出的那样。
然而,它们在两个非常微小和微妙的方面存在差异:
JVMS(Java虚拟机规范)对无界通配符有一个特殊规范,因为ClassFileFormat-Java5
指定无界通配符编码为*
,同时将对象绑定通配符编码为+Ljava/lang/Object;
。此类更改将通过任何分析字节码的库泄漏。编译器编写者也需要处理这个问题。来自revisions to "The class File Format"
从可再生性的角度来看,这些是不同的。 JLS 4.6 and 4.7将List<?>
编码为可复制类型,但List<? extends Object>
作为删除类型。添加.isReifiable()
(例如mjc lib)的任何图书馆作者都需要考虑到这一点,以遵守JLS术语。来自JLS 4.6 and 4.7。
答案 1 :(得分:18)
作为一个节奏点,如果类/接口/构造函数/方法声明了一个绑定(extends Object
除外),则会有所不同。
interface Donkey<T extends Thing> { }
...
Donkey<? extends Object> foo; // FAIL
答案 2 :(得分:4)
从实验开始,似乎{,List<?>
和List<? extends Object>
两种方式都是赋值兼容的,并且使用其中一种方法可以使用其中一种方法覆盖签名的方法。如,
import java.util.List;
class WildcardTest<T> {
public void foo(List<? extends T> bar) {}
}
class WildcardTest2 extends WildcardTest<Object> {
@Override
public void foo(List<?> bar) {super.foo(bar);}
}
答案 3 :(得分:2)
这很复杂......
对于任何类型变量T
,规范都说http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4
每个类型变量都有一个绑定。如果没有为类型变量声明绑定,则假定为Object。
有人会认为对于通配符也是如此,而?
应该只是? extends Object
的简写。
然而,在搜索规范时,根本没有证据表明通配符必须具有上限(或下限)。 “无界”?
与有界通配符的处理方式截然不同。
我们可以从子类型规则中推断出,List<?>
和List<? extends Object>
是彼此的子类型,即它们基本上相同的类型。
但该规范仍然单独对待它们。例如,http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List<?>
是一种可重复的类型,但List<? extends Object>
不是,这意味着
// ok
List<?>[] xx = {};
// fail
List<? extends Object>[] yy = {};
// ok
boolean b1 = (y instanceof List<?>);
// fail
boolean b2 = (y instanceof List<? extends Object>);
我不明白为什么。说通配符必须有上限和下限,默认为Object
和null type
似乎完全没问题。
答案 4 :(得分:-1)
java中的所有内容除了基元之外都扩展了Object,所以不会,没有区别。 Autoboxing允许使用原语,因此可以说java中的所有内容都是一个对象。
答案 5 :(得分:-1)
<? extends Object>
与<?>
完全相同。对不起,我没有参考方便,但是......确实如此。 :)