Search code examples
javacovariancevariance

How to make covariant Consumer<? extends Base> work?


This is the smallest code sample I could come up with to illustrate the problem:

public void consumeDerived(Consumer<Derived> derivedConsumer, Derived derivedParameter) {
    consumeBase(derivedConsumer, derivedParameter);
}

public void consumeBase(Consumer<? extends Base> baseConsumer, Base baseParameter) {
    baseConsumer.accept(baseParameter);
}

The idea is that the call to consumeDerived simply gets passed along to the consumeBase method. To my understanding, the call baseConsumer.accept() should be able to take type Base or type Derived extends Base.

However I get the error: java: incompatible types: Base cannot be converted to capture#1 of ? Base.

What do I need to do to make this work?


Solution

  • The problem is that Consumer<? extends Base> is a consumer of something which extends a Base. It may be a Consumer<Derived>, and that wouldn't be able to accept a Base as an argument - it's not specific enough.

    You can add a generic type parameter to solve this:

    public <T extends Base> void consumeBase(Consumer<T> baseConsumer, T baseParameter) {
        baseConsumer.accept(baseParameter);
    }
    

    It's also worth noting that consumeDerived is now superfluous.