Java Generics argument mismatch

I have an Interface Worker like below:

public interface Worker<T> {

    public void doAllTasks (List<? extends T> tasks);
}

There is an Abstract Class that uses above interface,

public abstract class AbstractWorker<T> implements Worker<T> {
    ...
    public abstract void doAllTasks (List<? extends T> tasks);
    ...
}

And there is a concrete Worker extending from this Abstract class,

public class ConcreteWorker<T extends Task> extends AbstractWorker<T>  {

    @Override
    public void doAllTasks(List<? extends T> tasks) {
    ....
    }
}

Notice the Task in the above class definition? That is an interface. SpecialTask is a concrete class that implements Task interface. Now once this structure is there, I wish to use this classes in my main Application like below:

Class Application {
    public AbstractWorker<? extends Task> myWorker;

    main() {
        ....
        List<SpecialTask> listOfTasks = new ArrayList<SpecialTask>();
        myWorker = new ConcreteWorker<SpecialTask>();
        myWorker.doAllTasks (listOfTasks); <-------------- ERROR!!!
    }
}

IDE shows me the following error in the above marked line:

The method doAllTasks(List<? extends capture#3-of extends Task>) in the type
AbstractWorker<capture#3-of extends Task> is not applicable for the 
arguments (List<SpecialTask>)

What I am trying to do is - in my main Application I want to first declare the Abstract version of my Worker first and later, based on some logic I want to instantiate a concrete version of that worker. I do not know before hand which particular implementation of Task I will need (so it could be the SpecialTask or AnotherSpecialTask etc. - assuming both of them implements Task)

Honestly being new to Java, I could not make any head or tail of that error message. Can someone please show me where am I going wrong?

Jon Skeet
people
quotationmark

The problem is that the type of myWorker is just AbstractWorker<? extends Task> - in other words, it doesn't know that the type argument is really SpecialTask. It could be an AbstractWorker<SomeOtherTask>, which wouldn't know what to do with a List<SpecialTask>.

If you only ever want myWorker to hold a worker that can deal with SpecialTask, you can just use:

public AbstractWorker<SpecialTask> myWorker;

That's still not depending on ConcreteWorker, but it is saying that it's definitely not just an AbstractWorker<SomeOtherTask> for example.

people

See more on this question at Stackoverflow