可能重复:
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>();
}
}
答案 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>
是彼此的子类型,即它们基本上相同的类型。 (扣除取决于E
中interface 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>);
我不明白为什么。说通配符必须有上限和下限,默认为Object
和null type
似乎完全没问题。
答案 1 :(得分:1)
两者都是相同的,因为Java中的所有对象都扩展Object
。我更喜欢List<?>
,因为它更简洁。
答案 2 :(得分:1)
类似于每个班级MyClass extends Object
List<? extends Object>
与List<?>
的相同方式。
答案 3 :(得分:0)
虽然我抄袭Marko,为此我道歉,他的评论是正确答案。
没有区别,因为每个类型都隐含extends Object
。