列出<! - ? - > vs List <! - ? extends Object - >

时间:2013-01-15 20:47:47

标签: java generics

  

可能重复:
  What’s the difference between <?> and <? extends Object> in Java Generics?

我发现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 个答案:

答案 0 :(得分:9)

这很复杂......

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

  

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

有人会认为对于通配符也是如此,而?应该只是? extends Object的简写。

然而,在搜索规范时,根本没有证据表明通配符必须具有上限(或下限)。 “无界”?与有界通配符的处理方式截然不同。

我们可以从子类型规则推断,List<?>List<? extends Object>是彼此的子类型,即它们基本上相同的类型。 (扣除取决于Einterface 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>);

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

类似于每个班级MyClass extends Object List<? extends Object>List<?>的相同方式。

答案 3 :(得分:0)

虽然我抄袭Marko,为此我道歉,他的评论是正确答案。

没有区别,因为每个类型都隐含extends Object