Search code examples
javacallbackjava-8deferredcallable

Java 8 Deferring Execution of Method


I have a class hierarchy like this:

public abstract class AbstractFoo {
    abstractMethod(/*parameters*/) {
        //do something;
    }
}

public class Foo extends AbstractFoo {
    public String doSomething(int id, int value, FooB b, FooC c) {
        //do something;
    }

    public void doSomethingElse() {
        abstractMethod(param1, param2);
    }
}

I want to be able to pass the doSomething method as a method parameter to abstractMethod. I tried something like this:

public abstract class AbstractFoo {
    abstractMethod(/*parameters*/, Callable<String> method) {
        //do something;
        method.call();
    }
}

public class Foo extends AbstractFoo {
    Callable<String> doSomething = (int id, int value, FooB b, FooC c) -> {
        //do something;
    };

    public void doSomethingElse() {
        abstractMethod(param1, param2, doSomething);
    }
}

But I'm getting the following error:

Error:(37, 40) java: incompatible types: incompatible parameter types in lambda expression: wrong number of parameters: expected 0 but found 4

So clearly I'm not doing this correctly. What exactly is the proper Java 8 way to achieve what I want?

Edit 1: Based on comments, here is an attempt at a better solution:

@FunctionalInterface
public interface Fazz<T> {
    String createStuff(int id, int value, T value1, T value2);
}

public abstract class AbstractFoo {
    abstractMethod(Fazz<T> interfc) {
        interfc.createStuff(/* pass parameters? */);
    }
}

public class Foo extends AbstractFoo {
    Fazz<String> doSomething = (int id, int value, String value1, String value2) -> {
        //do something;
    };

    public void doSomethingElse() {
        abstractMethod(doSomething);
    }
}

Solution

  • Callable interface has only one method: call() which takes zero arguments, hence the error.

    If you want to be able to pass a lambda you should implement a FunctionalInterface, for example:

    @FunctionalInterface
    interface DoSomething<T> {
        T doSomething(int id, int value, FooB b, FooC c);
    }
    

    and then you'll be able to create and pass such a lambda:

    DoSomething<String> doSomething = (int id, int value, FooB b, FooC c) -> {
            //do something (that returns a string)
    };
    

    Further, a Callable is used to run logic in a separate thread. The code that you posted above does not do that, which means that you can do the exact same work without using a Callable.

    In case you do want to run this logic in a separate thread, you can create a Callable that calls doSomething. Still, in order to run it in a separate thread you should use an ExecutorService.

    Pay attention: a FunctionalInterface can have only one abstract method (it can have additional default methods - since they are not abstract).