Consider following code:
public List<?> concatLists( List<?> ... aLists )
{
List<?> result = new ArrayList<>();
for ( int i = 0; i < aLists.length; i++ )
{
result.addAll( aLists[i]);
}
return result;
}
Compiler (java8) complains in result.addAll(...): "The method addAll(Collection) in the type List is not applicable for the arguments (List)".
But if the result is declared as
List<Object>
everything is fine.
Until now I assumed that the ? stands for "any type", which - so my assumption - always must be at least an Object. Obviously my assumption is not correct. So I have following questions (which may have the same answer):
Why does the compiler does not allow to addAll() if the target is also a List?
What is the exact difference between:
List<?> List<Object> List<? extends Object>
Each of this lists cannot contain something which is NOT an Object.
Edited to clarify
consider following code:
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
Each of this list can only contain Objects (or derivations of it) which is proven by the valid get calls on each of them.
Because I always deal with Object, I do not see any reason why the errorneous lines should not be allowed, especially the ones where the plainObject List (without super or extends) is involved.