19

I have a generic private method which does common tasks and is used by other methods. The generic method has if and else conditions to support other methods that are called. Example:

private void myGenericMethod(String name, int age){
  common task1;
  common task2;
  if(name!= null && name.length > 0){
     specific task 1;
     specific task 2;
  } else{
     specific task 3;
     specific task 4;
  }
  if(age > 18){
     specific task 1`;
     specific task 2`;
  }
}

I want to use Java 8 lambda and I have created a functional interface called Invoker with a invoke method.

public interface Invoker{
  public void invoke()
}

Now my generic method looks like this and the public method handles the invoke function callback appropriately:

private void myGenericMethod(Invoker invoker){
  common task1;
  common task2;
  invoker.invoke();
}  

Is there a functional interface in the JDK that I can use instead of creating this interface by myself?

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
zilcuanu
  • 3,451
  • 8
  • 52
  • 105
  • You can have a look into the [`java.util.function`](https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html) package and select which one suits your requirements. I couldn't suggest one because I don't know if your specific tasks has an argument (or more) ect ... – KarelG Aug 04 '17 at 06:47

3 Answers3

44

Package java.util.function does not contain a functional interface with a method that does not require any parameter and returns void. But you can use Runnable interface instead.

private void myGenericMethod(Runnable runnable){
    common task1;
    common task2;
    //consider checking if runnable != null to avoid NPE
    runnable.run();
}  

Then the invocation would look pretty simple:

myGenericMethod(() -> {
    //do something fancy
    System.out.println("Hello, world!");
});

Other options

There are other functional interfaces you may be interested in, for example:

  • Supplier<T> if you want to return a value of T without passing any parameters
  • Function<T,R> if you want to pass a value of T and return a value of R
  • Consumer<T> if you want to pass value T as a parameter and return void

Why there is no alternative for Runnable interface?

Using Runnable interface for a lambda that does not return nothing and does not expect any parameters may sound controversial for many programmers. Runnable was invented for running a code in a separate thread and many programmers identify this class with multithreading. Even documentation says:

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.

Someone already asked similar question 2 years ago and if you take a look at this comment and Brian Goetz's reaction to it you will understand that Java language designers came to a conclusion that there is no need to create another functional interface that mimics implementation of Runnable interface.

elect
  • 6,765
  • 10
  • 53
  • 119
Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
  • 2
    `Runnable` is intended to encapsulate work that can be done asynchronously. Using it in this context is confusing[citation needed]. If the intention is misinterpreted by other developers it can lead to serious issues. It's been suggested to make your own interface called `Operation`, `Executable` or something along those lines. – Mark Jeronimus Aug 04 '17 at 07:40
  • If you're going with the 'Invoke' terminology I suggest the interface name `Invokable` instead, to stay in line with the naming conventions. – Mark Jeronimus Aug 04 '17 at 08:11
  • The reason I do not want to user `Runnable` is it raises the co developers eye brows when they see Runnable and create confusion. I will stick with Invokable. But to my surprise there is no such interface is Java8 – zilcuanu Aug 05 '17 at 04:43
  • Yeah, there should be one in `java.util.function`. Using your custom one instead will be best in this case. – Szymon Stepniak Aug 05 '17 at 04:52
  • @MarkJeronimus But does Java8 does not have a functional interface out of the box to handle this? I wonder what made them not to have a functional interface similar to Runnable interface – zilcuanu Aug 08 '17 at 09:23
  • 1
    @zilcuanu Brian Goetz explained why there is no alternative for `Runnable` interface here - https://stackoverflow.com/questions/27973294/function-with-no-args-and-no-return-type-void-in-java-8?lq=1#comment44339647_27973294 Quote: "I'm sure that the existence of `Runnable` is why the Java designers felt they didn't need to add another functional interface", Brian confirmed that. – Szymon Stepniak Aug 08 '17 at 09:32
10

There is also the possibility to use Consumer<Void>. It could look like this

public void init(Consumer<Void> callback) {
    callback.accept(null);
}

init((Void) -> done());
Murat Karagöz
  • 35,401
  • 16
  • 78
  • 107
0

I suggest to use Consumer as callback interface. Comparing it with the JavaScript language, callbacks are bound with a scope. Therefore, if you make use of Consumer interface then you can pass the scope as parameter to the function. Ex:

public void startTracer(String tracerName, Event boundEvent) {
    executeOnTracer(tracer -> tracer.startTracer(tracerName, boundEvent));
}
...
private void executeOnTracer(Consumer<Tracer> callback) {
    TracerController tracer = null;
    if (isTracerActive()) {
        tracer = getTracer();
    }
    Optional.ofNullable(tracer).ifPresent(callback::accept);
}
João Pedro Schmitt
  • 1,046
  • 1
  • 11
  • 25