List<?>与List<? extends Object>的区别

14

可能是重复问题:
Java泛型中<?>和<? extends 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>();
}
}

6
完全没有区别,“extends Object”是冗余的,否则会默认假设,就像写“class F extends Object”一样。 - Marko Topolnik
1
我敢打赌它们是等价的,因为Java中的所有类都隐式扩展了Object - murgatroid99
1
完全没有区别,这是语言设计/语法的结果。 - nullpotent
你也可以查阅PECS原则(Producer Extends Consumer Super)。 - Greg
同时:https://dev59.com/p3I-5IYBdhLWcg3wF0Uc - Paul Bellora
显示剩余2条评论
4个回答

13

这很复杂...

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

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

人们可能认为通配符也是如此,并且?只是? extends Object的简写。

然而,在规范中搜索,根本没有证据表明通配符必须具有上限(或下限)。"无限制的"?与有界通配符一致地处理不同。

我们可以从子类型规则推断出List<?>List<? extends Object>彼此是子类型,即它们基本上是相同的类型。(推断依赖于interface List<E>中的E具有隐式上界Object的事实;但规则不要求通配符有边界)

尽管如此,规范仍然将两者区别对待。例如,http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.7List<?>是可重用类型,但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


@iccthedral - 应用于List情况,List<?>大致类似于某些X<:Object的List<X> - irreputable
1
是的,这就是我的观点。X <: B 应该 (?) 是一种包容性子类型关系,但我找不到相关的参考资料。这只是因为 T extends C 也是包容性的。 - nullpotent
+1 好的JLS侦探工作 :) - Marko Topolnik
JLS8 - 通配符 ? extends Object 等同于无限定通配符 ?。 - ZhongYu
javac8 - 允许 List<? extends Object>[],但不允许 instanceof List<? extends Object> - ZhongYu
显示剩余5条评论

1

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


1

就像每个类都会扩展Object一样,List<? extends Object>List<?>是相同的。


0

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

因为隐式地每个类型都extends Object,所以没有区别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接