7

The compiler gives me this error "Target Type of lambda expression must be an interface" for this code:

Task<Iterable<Showing>> task = () -> sDAO.listFiltered();

listFiltered()'s return type is Iterable<Showing>. How can I use the Task interface with lambda?

Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106
Domien
  • 395
  • 5
  • 18

1 Answers1

13

Task is an abstract class, not an interface, and so it cannot be directly created with a lambda expression.

You would typically just use an inner class to subclass Task:

Task<Iterable<Showing>> task = new Task<Iterable<Showing>>() {
    @Override
    public Iterable<Showing> call throws Exception {
        return sDAO.listFiltered();
    }
});

If you want the functionality of creating a Task with a lambda expression, you could create a reusable utility method to do that for you. Since the abstract method call that you need to implement in Task has the same signature as the interface method in Callable, you could do the following:

public class Tasks {

    public static <T> Task<T> create(Callable<T> callable) {
        return new Task<T>() {
            @Override
            public T call() throws Exception {
                return callable.call();
            }
        };
    }
}

Since Callable is a FunctionalInterface (i.e. an interface with a single abstract method), it can be created with a lambda expression, so you could do

Task<Iterable<Showing>> task = Tasks.create(() -> sDAO.listFiltered());

There is an explanation of why lambdas are not allowed to be used to create (effectively) subclasses of abstract classes with a single abstract method on the OpenJDK mailing list.

Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Only problem now is that I can't do it with methods thats return void type. It says "void cannot be converted to Void" – Domien May 07 '15 at 21:23
  • Neither the `call` method in `Task` or in `Callable` can be `void`. Instead, declare them to return a `Void` and return `null` (the only legal value for a `Void` reference type). – James_D May 07 '15 at 22:08