4

Explaining the issue with an example:

public class DataWrapper<T> {
    T data;
};

DataWrapper<Object> obj1 = new DataWrapper<Object>();

List<DataWrapper<?>> anyDataList = Arrays.asList(obj1); //this doesn't work

DataWrapper<Integer> objInt = new DataWrapper<Integer>();
anyDataList = Arrays.asList(obj1, objInt); //this work

I couldn't understand why "Arrays.asList(obj1)" doesn't work?

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332

1 Answers1

9

Java 7 was stupid (not it wasn't) when inferring type arguments for generic methods. For example, it would use the declared type of an argument to infer the type regardless of the context of the method invocation. So in

Arrays.asList(obj1);

the type argument would be inferred as

DataWrapper<Object>

the method's return type would then be List<DataWrapper<Object>> which is no assignable to a List<DataWrapper<?>>.

In

Arrays.asList(obj1, objInt);

the type is inferred from both arguments. A common type is found between the two. In this case, that's ? extends Object. The method return type becomes List<DataWrapper<? extends Object>> which is assignable to List<DataWrapper<?>>.

In Java 8, what you posted works out of the box. In Java 7, you can provide an explicit type argument to make it work

List<DataWrapper<?>> anyDataList = Arrays.<DataWrapper<?>>asList(obj1); 
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • +1 for the explanation. Can you also provide a workaround for people using Java 7? – StriplingWarrior Aug 27 '14 at 19:43
  • DataWrapper can be assigned to DataWrapper>. Extending this logic, I expected the wildcard to work for second level nested type parameters also: List> should be assignable to List> – user1447561 Aug 27 '14 at 19:45
  • 1
    @user1447561 Read [this](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p). It's not immediately obvious that they aren't. – Sotirios Delimanolis Aug 27 '14 at 19:46