Java中的无界通配符

时间:2010-01-06 20:33:24

标签: java generics bounded-wildcard

无界通配符之间是否存在差异,例如<?>和有界通配符,其边界为Object,例如<? extends Object>

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

6 个答案:

答案 0 :(得分:32)

从大多数人的实际角度来看,<? extends Object><?>相同,就像所有人在此提出的那样。

然而,它们在两个非常微小和微妙的方面存在差异:

  1. JVMS(Java虚拟机规范)对无界通配符有一个特殊规范,因为ClassFileFormat-Java5指定无界通配符编码为*,同时将对象绑定通配符编码为+Ljava/lang/Object;。此类更改将通过任何分析字节码的库泄漏。编译器编写者也需要处理这个问题。来自revisions to "The class File Format"

  2. 从可再生性的角度来看,这些是不同的。 JLS 4.6 and 4.7List<?>编码为可复制类型,但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>);

我不明白为什么。说通配符必须有上限和下限,默认为Objectnull type似乎完全没问题。

答案 4 :(得分:-1)

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

答案 5 :(得分:-1)

<? extends Object><?>完全相同。对不起,我没有参考方便,但是......确实如此。 :)

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