Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics Curiosity

I have an interface A, which class B implements.

The following generic method works

public static <T, U extends T> List<T> listFactory(Collection<U> source) {
    return new ArrayList<T>(source);
}

but

public static <T> List<T> listFactory(Collection<? extends T> source) {
    return new ArrayList<T>(source);
}

does not (compilation error, type mismatch), when I am directing the output into

List<A> tester = listFactory(B.defaultCollectionFactory(3));

defaultCollectionFactory(int count) statically provides a collection of Bs, with a default labeling scheme.

Any insights as to why that is? It seems like the generic U and wildcard are doing the same thing.

like image 772
Carl Avatar asked Oct 03 '09 19:10

Carl


2 Answers

The compiler is inferring a different type parameter for the listFactory method than you expect. It infers that T is type B, so the signature is effectively List<B> listFactory(Collection<? extends B> source). Specify the type parameter A by being explicit in the method invocation:

List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));
like image 183
erickson Avatar answered Oct 20 '22 16:10

erickson


In the first construct, you are specifying that you are returning a List of the interface of the item that was passed in. You specify the relationship between the passed in Object and the return Object type in the U extends T direction. In this case, the compiler can associate A and B with T andU respectively.

In the second, there is no such differentiation, so the compiler assumes that T refers to B and will type the return value as List<B>. You then fall into the trap where, although B is an instance of A, List<B> is not an instance of List<A>. The compiler will complain:

Type mismatch: cannot convert from List<B> to List<A>

You will find that, with the first construct, you have the liberty of specifying a List of any interface the B implements or any superclass in the B hierarchy (List<Object>, for example), and the compiler will not complain.

like image 38
akf Avatar answered Oct 20 '22 14:10

akf