【问题标题】:What is the difference between List<Something> and List<? extends Something>? [duplicate]List<Something> 和 List< 有什么区别?扩展某事>? [复制]
【发布时间】:2013-09-21 17:52:57
【问题描述】:

这两个Lists有区别吗?

List<Something> a;
List<? extends Something> b;

例如我知道

List<Object> a;
List<?> b;
List c;

List<Something> a;
List<? extends SomeInterfaceSomethingImplements> b;

都是不同的,但是这些呢?如果将Something 替换为Object 会有什么不同吗?

List<Object> a;
List<? extends Object> b;

【问题讨论】:

  • 将字段类型设为List&lt;Object&gt; 只允许您为其分配List&lt;Object&gt;。由于类型擦除,List&lt;String&gt; 不被视为 List&lt;Object&gt;。可以为声明为List&lt;? extends Object&gt; 的引用分配属于Object 的任意子类的元素列表(这适用于Java 中的所有类)。这可能意味着List&lt;Object&gt;List&lt;String&gt;List&lt;Whatever&gt;
  • @Tom Right,但我很确定这不是因为类型擦除。 StringObject 已经存在了,只是检查,与擦除类型无关。
  • 我看不出这是怎么复制的。在另一个问题中,提问者正在比较&lt;Date&gt;&lt;? extends Serializable&gt;。在我的情况下,例如 &lt;Date&gt;&lt;? extends Date&gt;

标签: java generics


【解决方案1】:

List&lt;Something&gt;Something 类型的对象列表。 List&lt;? extends Something&gt; 是扩展 Something 的某些特定类型的对象列表。

因此,List&lt;Object&gt; 可以拥有任何扩展 Object 的类的对象。 但List&lt;? extends Object&gt; 只能初始化或分配为扩展Object 的特定类的对象列表

什么时候有用?假设您要编写一个方法,该方法采用 ObjectsList 并打印每个项目:

void print(List<Object> list) {
    for (Object obj: list) {
        System.out.println(obj)
    }
}

现在,假设您有一个List&lt;Integer&gt;。不能将它传递给上述方法,因为print 需要List&lt;Object&gt;,而List&lt;Integer&gt; 不能分配给List&lt;Object&gt;。为了解决这个问题,我们将print 重新定义为:

void print2(List<? extends Object> list) {
    for (Object obj: list) {
        System.out.println(obj)
    }
}

现在,我们可以将 Object 的任何子类的 List 传递给 print2print2 将接受 List&lt;Integer&gt;List&lt;String&gt; 等。

另一方面,您不能在print2 内的列表中添加任何内容,因为print2 不知道所使用的Object 的具体子类型。因此,您只能在不需要向List 添加任何内容的方法中使用? extends ...

【讨论】:

  • List&lt;? extends Object&gt; 也可以初始化为List&lt;Object&gt;
  • @Ryan,是的,可以。 ? 的用处在于它也可以分配给List&lt;Integer&gt;,而您不能将List&lt;Integer&gt; 分配给List&lt;Object&gt;
  • 第2段第2句的措辞听起来好像不行。
【解决方案2】:

正如其他人所提到的,List&lt;Something&gt;Something 类型的对象列表,而List&lt;? extends Something&gt; 将被初始化为不同对象类型的列表,只要对象类型扩展Something

List&lt;Object&gt; 将是Object 类型的对象列表。

List&lt;? extends Object&gt; 可以初始化为扩展 Object 的任何数据类型的列表。

这里有一些代码显示了使用Object? extends Object 相比会发生什么:

import java.util.ArrayList;

public class test {
    class A {}

    public static void main(String[] args) {
        // No error
        ArrayList<Object> arrObj = new ArrayList<Object>();

        // Error
        ArrayList<Object> arrObj2 = new ArrayList<A>();

        // No Error
        ArrayList<? extends Object> arrExt = new ArrayList<Object>();

        // No Error
        ArrayList<? extends Object> arrExt2 = new ArrayList<A>();
    }

}

【讨论】:

    【解决方案3】:

    List&lt;Something&gt; 表示实现应该类似于ArrayList&lt;Something&gt;。但另一种情况List&lt;? extends Something&gt; 意味着实现可以是ArrayList&lt;Something&gt;ArrayList&lt;SomethingChild&gt; 其中SomethingChild 扩展Something

    你可以分配

    List<? extends Something> list = new ArrayList<SomethingChild>();
    

    而你不能分配

    List<Something> list = new ArrayList<SomethingChild>();
    

    这将导致编译错误。

    您可以了解有关泛型和泛型中使用的通配符的更多信息,以获得一些洞察力

    【讨论】:

      【解决方案4】:

      第一个是对象类型的集合,第二个是对象的子类型的集合。

      【讨论】:

        猜你喜欢
        • 2020-08-20
        • 1970-01-01
        • 2013-01-31
        • 2019-03-15
        • 2015-11-08
        • 2021-04-23
        • 1970-01-01
        • 2010-10-15
        • 1970-01-01
        相关资源
        最近更新 更多