10

可能重复:
<?> 和 <? 之间有什么区别?在 Java 泛型中扩展 Object>?

我发现了这一点List<?>List<? extends Object>以同样的方式行事。至于我,他们之间没有区别。如果我不正确,你能解释一下区别吗?

import java.util.ArrayList;
import java.util.List;

public class TestClass {

static void func1(List<?> o, Object s) {
    o.add(null); // only null
    o.add(s); // wrong
    o.get(0);  // OK
}

static void func2(List<? extends Object> o, Object s) {
    o.add(null); // only null
    o.add(s); // wrong
    o.get(0); // OK
}

public static void main(String[] args) {
    func1(new ArrayList<String>(), new Integer(1));
    func2(new ArrayList<String>(), new Integer(1));

    List<? extends Object> list1 = new ArrayList<Object>();
    List<?> list2 = new ArrayList<Object>();

    List<? extends Object> list3 = new ArrayList<String>();
    List<?> list4 = new ArrayList<String>();
}
}
4

4 回答 4

9

这很复杂...

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

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

有人会认为通配符也是如此,?应该只是? extends Object.

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

我们可以从子类型化规则中推断,List<?>List<? extends Object>是彼此的子类型,即它们基本上是相同的类型。(推论取决于Eininterface List<E>具有隐式上限这一事实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>);

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

于 2013-01-15T22:07:41.480 回答
1

两者都是相同的,因为 Java 中的所有对象都可以扩展Object。我更喜欢List<?>,因为它更简洁。

于 2013-01-15T20:53:23.230 回答
1

类似于如何MyClass extends Object为每个类List<? extends Object>是一样的List<?>

于 2013-01-15T20:54:36.413 回答
0

尽管我抄袭了 Marko,对此我深表歉意,但他的评论是正确的答案。

没有区别,因为隐含的每个 type extends Object

于 2013-01-15T20:55:32.203 回答