Java中的无界通配符

无界通配符(例如和绑定通配符之间是否有区别,例如

我记得曾经在某处看过,早期的仿制药草稿有所不同,但是找不到那个来源了。

作为一个节奏点,如果类/接口/构造函数/方法声明了一个绑定(不是extends Object ),则会有所不同。

 interface Donkey { } ... Donkey foo; // FAIL 

从实际到大多数人, 相同,就像每个人在这里建议的那样。

但是,它们在两个非常微小和微妙的方面有所不同:

  1. JVMS(Java虚拟机规范)对无界通配符有一个特殊规范,因为ClassFileFormat-Java5指定无界通配符编码为* ,而将对象绑定通配符编码为+Ljava/lang/Object; 。 此类更改将通过任何分析字节码的库泄漏。 编译器编写者也需要处理这个问题。 从修订版到“类文件格式”

  2. 从再生性的角度来看,这些是不同的。 JLS 4.6和4.7将List编码为可重新类型,但List List为擦除类型。 添加.isReifiable() (例如mjc lib )的任何库编写者都需要考虑到这一点,以遵守JLS术语。 来自JLS 4.6和4.7 。

从实验来看,似乎是ListList List是双向兼容的,并且使用其中一个签名的方法可以使用另一个签名覆盖签名。 例如,

 import java.util.List; class WildcardTest { public void foo(List bar) {} } class WildcardTest2 extends WildcardTest { @Override public void foo(List bar) {super.foo(bar);} } 

这很复杂…

对于任何类型变量T ,规范说http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4

每个类型变量都有一个绑定。 如果没有为类型变量声明绑定,则假定为Object。

有人会认为对于通配符也是如此,并且? 应该只是一个简写? extends Object ? extends Object

然而,搜索规范,根本没有证据表明通配符必须具有上限(或下限)。 “无界” ? 与有界通配符一致地对待。

我们可以从子类型规则推导出ListList List是彼此的子类型,即它们基本上是相同的类型。

但该规范仍然分别对待它们。 例如http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7 List是一个可重新生成的类型,但List List不是,这意味着

  // ok List[] xx = {}; // fail List[] yy = {}; // ok boolean b1 = (y instanceof List); // fail boolean b2 = (y instanceof List); 

我不明白为什么。 说通配符必须有上限和下限,默认为Objectnull type似乎很好。

除了基元之外,java中的所有内容都扩展了Object,所以不会,没有区别。 Autoboxing允许使用原语,因此可以说java中的所有内容都是一个对象。

完全相同。 对不起,我没有参考方便,但是……确实如此。 🙂

编辑:当然,当我这么说时,我只是从特定的角度思考。 忽略我的答案(这是非常正确的downvoted)并看到真实故事的更高评价的答案。