Java:连接两个List <! - ? - >

时间:2016-08-09 13:32:24

标签: java generics type-safety

请考虑以下代码:

public List<?> concatLists( List<?> ... aLists )
{
    List<?> result = new ArrayList<>();

    for ( int i = 0; i < aLists.length; i++ )
    {
        result.addAll( aLists[i]);
    }

    return result;
}

编译器(java8)在result.addAll(...)中抱怨:“类型List中的方法addAll(Collection)不适用于参数(List)”。

但是如果结果声明为

    List<Object>
一切都很好。

到现在为止我假设了?代表“任何类型”,因此 - 我的假设 - 始终必须至少是一个对象。显然我的假设是不正确的。所以我有以下问题(可能有相同的答案):

  1. 如果目标也是List,编译器为什么不允许addAll()?

  2. 之间的确切区别是:

    List<?>
    List<Object>
    List<? extends Object>
    
  3. 每个列表都不能包含非对象的内容。

    编辑澄清

    考虑以下代码:

        List<? super Object> superObject = new ArrayList<>();
        List<? extends Object> extendObject = new ArrayList<>();
        List<?> plainObject = new ArrayList<>();
        List<Object> object = new ArrayList<>();
    
        Object obj = new Object();
        superObject.add( obj );     // valid
        extendObject.add( obj );    // ERROR
        plainObject.add( obj );     // ERROR
        object.add( obj);           // valid
    
        Integer aInt = Integer.valueOf(1);
        superObject.add( aInt );    // valid
        extendObject.add( aInt );   // ERROR
        plainObject.add( aInt );    // ERROR
        object.add( aInt);          // valid
    
        String str = "hello";
        superObject.add( str );     // valid
        extendObject.add( str );    // ERROR
        plainObject.add( str );     // ERROR
        object.add( str);           // valid
    
        superObject.addAll( superObject );  // valid
        superObject.addAll( extendObject ); // valid
        superObject.addAll( plainObject );  // valid
        superObject.addAll( object);        // valid
    
        extendObject.addAll( extendObject );    // ERROR
        extendObject.addAll( superObject );     // ERROR
        extendObject.addAll( plainObject );     // ERROR
        extendObject.addAll( object);           // ERROR
    
        plainObject.addAll( plainObject );  // ERROR
        plainObject.addAll( superObject );  // ERROR
        plainObject.addAll( extendObject ); // ERROR
        plainObject.addAll( object);        // ERROR
    
        object.addAll( plainObject );  // valid
        object.addAll( superObject );  // valid
        object.addAll( extendObject ); // valid
        object.addAll( object);        // valid
    
        Object o;
        o = superObject.get( 0 );  // valid
        o = extendObject.get( 0 ); // valid
        o = plainObject.get( 0 );  // valid
        o = object.get( 0 );       // valid
    

    这个列表中的每一个都只能包含对象(或它的派生),这些对象可以通过每个对象的有效get调用来证明。

    因为我总是处理Object,所以我没有看到为什么不允许使用错误行的原因,特别是那些涉及plainObject List(没有super或extends)的行。

0 个答案:

没有答案