Java中的无界通配符
无界通配符(例如和绑定通配符之间是否有区别,例如
?
我记得曾经在某处看过,早期的仿制药草稿有所不同,但是找不到那个来源了。
作为一个节奏点,如果类/接口/构造函数/方法声明了一个绑定(不是extends Object
),则会有所不同。
interface Donkey { } ... Donkey extends Object> foo; // FAIL
从实际到大多数人, extends Object>
extends Object>
与>
相同,就像每个人在这里建议的那样。
但是,它们在两个非常微小和微妙的方面有所不同:
-
JVMS(Java虚拟机规范)对无界通配符有一个特殊规范,因为
ClassFileFormat-Java5
指定无界通配符编码为*
,而将对象绑定通配符编码为+Ljava/lang/Object;
。 此类更改将通过任何分析字节码的库泄漏。 编译器编写者也需要处理这个问题。 从修订版到“类文件格式” -
从再生性的角度来看,这些是不同的。 JLS 4.6和4.7将
List>
编码为可重新类型,但List extends Object>
List extends Object>
为擦除类型。 添加.isReifiable()
(例如mjc lib )的任何库编写者都需要考虑到这一点,以遵守JLS术语。 来自JLS 4.6和4.7 。
从实验来看,似乎是List>
和List extends Object>
List extends Object>
是双向兼容的,并且使用其中一个签名的方法可以使用另一个签名覆盖签名。 例如,
import java.util.List; class WildcardTest { public void foo(List extends T> bar) {} } class WildcardTest2 extends WildcardTest
这很复杂…
对于任何类型变量T
,规范说http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4
每个类型变量都有一个绑定。 如果没有为类型变量声明绑定,则假定为Object。
有人会认为对于通配符也是如此,并且?
应该只是一个简写? extends Object
? extends Object
。
然而,搜索规范,根本没有证据表明通配符必须具有上限(或下限)。 “无界” ?
与有界通配符一致地对待。
我们可以从子类型规则推导出List>
和List extends Object>
List extends Object>
是彼此的子类型,即它们基本上是相同的类型。
但该规范仍然分别对待它们。 例如http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List>
是一个可重新生成的类型,但List extends Object>
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
似乎很好。
除了基元之外,java中的所有内容都扩展了Object,所以不会,没有区别。 Autoboxing允许使用原语,因此可以说java中的所有内容都是一个对象。
extends Object>
extends Object>
与>
完全相同。 对不起,我没有参考方便,但是……确实如此。 🙂
编辑:当然,当我这么说时,我只是从特定的角度思考。 忽略我的答案(这是非常正确的downvoted)并看到真实故事的更高评价的答案。