0

I am trying to do the following in Java using generics:

public class MyType {
    public void printBase(Collection<Base> bases) {
        for (Base base : bases) {
            System.out.println(base.toString());
        }
    }

    public <A extends Base> void myMethod(Collection<A> things) {
        // ...
        printBases(things); // Error here
        // ...
    }
}

The error I get is this:

The method printBases(Collection<Base>) in the type MyType is not applicable for the arguments (Collection<A>).

In this case, however, A extends Base so A is a Base. Shouldn't this method call be legal? If not, how can I solve this problem?

Max
  • 15,157
  • 17
  • 82
  • 127

2 Answers2

4

Generic types are invariant so the type used for Collection<Base> is not compatible with Collection<A>. You could use an upper bound generic type for the bases argument

public void printBase(Collection<? extends Base> bases) {
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • In my example this would work, but unfortunately, I do not have access to the `printBase` source code. – Max Jan 16 '14 at 16:50
3

Collection<A> does not extend Collection<Base> even though A extends Base. So it is absolutely normal to see this error at compile time.

Given that you cannot change the definition of printBase, here is a possible workaround.

import java.util.ArrayList;
import java.util.Collection;

class Base {

}

class A extends Base {

}

public class MyType {
    public void printBase(Collection<Base> bases) {
        for (Base base : bases) {
            System.out.println(base.toString());
        }
    }

    public <A extends Base> void myMethod(Collection<A> things) {
        Collection<Base> lst = new ArrayList<Base>();
        lst.addAll(things);
        printBase(lst);
    }
}
peter.petrov
  • 38,363
  • 16
  • 94
  • 159