334

Let's say I have the following functional interface in Java 8:

interface Action<T, U> {
   U execute(T t);
}

And for some cases I need an action without arguments or return type. So I write something like this:

Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };

However, it gives me compile error, I need to write it as

Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};

Which is ugly. Is there any way to get rid of the Void type parameter?

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Wickoo
  • 6,745
  • 5
  • 32
  • 45
  • 2
    Take a look at http://stackoverflow.com/questions/14319787/how-to-specify-function-types-for-void-not-void-methods-in-java8 – BobTheBuilder Apr 29 '15 at 13:47
  • 9
    If you need an action, as you defined it, it's not possible. However, your first example could fit in a `Runnable`, which what you are looking for `Runnable r = () -> System.out.println("Do nothing!");` – Alexis C. Apr 29 '15 at 13:49
  • 1
    @BobTheBuilder I don't want to use a Consumer as suggested in that post. – Wickoo Apr 29 '15 at 13:50
  • @AlexisC. the problem is that Runnable cannot be made a subtype of my function type. – Wickoo Apr 29 '15 at 13:51
  • In java if in method signature you have return type - you must return something in method implementation. – Divers Apr 29 '15 at 13:52
  • 2
    Matt's answer makes the types work, but what does the caller do when it gets a null return value? – Stuart Marks Apr 29 '15 at 15:06
  • 8
    You could cross fingers and hope that suggestions 2 & 3 in [this post](http://mail.openjdk.java.net/pipermail/compiler-dev/2015-January/009233.html) get accepted for Java 9! – assylias Apr 29 '15 at 15:23

10 Answers10

873

Use Supplier if it takes nothing, but returns something.

Use Consumer if it takes something, but returns nothing.

Use Callable if it returns a result and might throw (most akin to Thunk in general CS terms).

Use Runnable if it does neither and cannot throw.

Roberto Morávia
  • 492
  • 1
  • 6
  • 13
x1a0
  • 9,984
  • 5
  • 22
  • 30
  • 1
    As an example I did this to wrap "void" return call : `public static void wrapCall(Runnable r) { r.run(); }`. Thanks – Maxence Jun 29 '17 at 11:54
  • Does not help if it must throw a checked exception, unfortunately. – Jesse Glick Apr 02 '18 at 19:19
  • Consumer allows only one input parameter – Murat Erkenov May 08 '18 at 12:44
  • 23
    As completion for this answer, which wouldn't be worth an edit: you can also use BiConsumer (takes 2, returns 0), Function (takes 1, return 1) and BiFunction (takes 2, returns 1). Those are the most important to know – CLOVIS Jul 31 '18 at 21:23
  • One note here is that [Runnable](https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html) cannot throw and really best used when you want to execute asynchronously. If you want to have a functional interface more akin to [Thunk](https://en.wikipedia.org/wiki/Thunk), you should use [Callable](https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Callable.html), which can throw. – Avery Michelle Dawn Nov 29 '18 at 19:25
  • 2
    Is there anything like Callable (which throws an exception in its call() method) but does require any return value? – dpelisek May 05 '19 at 08:18
  • Also: `Function` if it takes a single argument of type T and returns a value of type R. AFAIK It cannot throw. – Akhmedzianov Danilian Nov 13 '19 at 09:34
  • I wish JDK could reuse the Unix Philosophy terminology: cantrip, filter, source and sink – Sridhar Sarnobat Jul 08 '22 at 00:42
  • I wanted a strongly typed NO_OP in the spirit of `@FunctionalInterface`, instead of using `Runnable`: https://stackoverflow.com/a/76985309/501113 – chaotic3quilibrium Aug 28 '23 at 17:55
407

I think this table is short and usefull:

Supplier       ()    -> x
Consumer       x     -> ()
BiConsumer     x, y  -> ()
Callable       ()    -> x throws ex
Runnable       ()    -> ()
Function       x     -> y
BiFunction     x,y   -> z
Predicate      x     -> boolean
UnaryOperator  x1    -> x2
BinaryOperator x1,x2 -> x3

As said on the other answers, the appropriate option for this problem is a Runnable

Craigo
  • 3,384
  • 30
  • 22
rado
  • 5,720
  • 5
  • 29
  • 51
134

The syntax you're after is possible with a little helper function that converts a Runnable into Action<Void, Void> (you can place it in Action for example):

public static Action<Void, Void> action(Runnable runnable) {
    return (v) -> {
        runnable.run();
        return null;
    };
}

// Somewhere else in your code
 Action<Void, Void> action = action(() -> System.out.println("foo"));
Matt
  • 17,290
  • 7
  • 57
  • 71
  • 4
    This is the cleanest workaround you could get, IMO, so +1 (or with a static method in the interface itself) – Alexis C. Apr 29 '15 at 14:12
  • Konstantin Yovkov's solution below (with @FunctionalInterface) is a better solution, because it does not involve generics and does not require extra code. – uthomas Oct 01 '16 at 05:45
  • @uthomas Sorry, I don't see an answer involving `@FunctionalInterface`. He merely says, that it's not possible to extend it... – Matt Oct 09 '16 at 14:29
  • 1
    Hi @Matt, sorry. I reacted too fast. For the given question you answer is perfectly valid. Unfortunately, my vote is locked, so I cannot remove my -1 on this answer. Two notes: 1. Instead of `Runnable` action should take a custom `@FunctionalInterface` something called `SideEffect`, 2. the need for such helper function highlights that something weird is going on and probably the abstraction is broken. – uthomas Oct 11 '16 at 09:47
43

The lambda:

() -> { System.out.println("Do nothing!"); };

actually represents an implementation for an interface like:

public interface Something {
    void action();
}

which is completely different than the one you've defined. That's why you get an error.

Since you can't extend your @FunctionalInterface, nor introduce a brand new one, then I think you don't have much options. You can use the Optional<T> interfaces to denote that some of the values (return type or method parameter) is missing, though. However, this won't make the lambda body simpler.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
33

You can create a sub-interface for that special case:

interface Command extends Action<Void, Void> {
  default Void execute(Void v) {
    execute();
    return null;
  }
  void execute();
}

It uses a default method to override the inherited parameterized method Void execute(Void), delegating the call to the simpler method void execute().

The result is that it's much simpler to use:

Command c = () -> System.out.println("Do nothing!");
Jordão
  • 55,340
  • 13
  • 112
  • 144
5

In the same way of @rado answer with the parameters and the description:

/*----------------------
Represents an operation
that accepts two input
arguments and returns no
result.
*/
BiConsumer<T,U>         (T x, U y)  -> ()


/*----------------------
Represents a function
that accepts two arguments
and produces a result.
*/
BiFunction<T,U,R>       (T x, U y)   -> R z


/*----------------------
Represents an operation
upon two operands of the
same type, producing a
result of the same type
as the operands.
*/
BinaryOperator<T>       (T x1, T x2) -> T x3


/*----------------------
A task that returns a
result and may throw an
exception.
*/
Callable<V>             ()    -> V x   throws ex


/*----------------------
Represents an operation
that accepts a single
input argument and returns
no result.
*/
Consumer<T>             (T x)   -> ()


/*----------------------
Represents a function that
accepts one argument and
produces a result.
*/
Function<T,R>           (T x)   -> R y


/*----------------------
Represents a predicate
(boolean-valued function)
of one argument.
*/
Predicate<T>            (T x)   -> boolean


/*----------------------
Represents a portion of
executable code that
don't recieve parameters
and returns no result.
*/ 
Runnable                ()    -> ()


/*----------------------
Represents a supplier of
results.
*/
Supplier<T>             ()      -> T x

/*----------------------
Represents an operation 
on a single operand that
produces a result of the
same type as its operand.
*/
UnaryOperator<T>        (T x1)  -> T x2

fonts:

[1] https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

[2] https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html

[3] https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

Anibal Anto
  • 99
  • 1
  • 2
3

I don't think it is possible, because function definitions do not match in your example.

Your lambda expression is evaluated exactly as

void action() { }

whereas your declaration looks like

Void action(Void v) {
    //must return Void type.
}

as an example, if you have following interface

public interface VoidInterface {
    public Void action(Void v);
}

the only kind of function (while instantiating) that will be compatibile looks like

new VoidInterface() {
    public Void action(Void v) {
        //do something
        return v;
    }
}

and either lack of return statement or argument will give you a compiler error.

Therefore, if you declare a function which takes an argument and returns one, I think it is impossible to convert it to function which does neither of mentioned above.

pnadczuk
  • 907
  • 1
  • 7
  • 12
3

That is not possible. A function that has a non-void return type (even if it's Void) has to return a value. However you could add static methods to Action that allows you to "create" a Action:

interface Action<T, U> {
   U execute(T t);

   public static Action<Void, Void> create(Runnable r) {
       return (t) -> {r.run(); return null;};
   }

   public static <T, U> Action<T, U> create(Action<T, U> action) {
       return action;
   } 
}

That would allow you to write the following:

// create action from Runnable
Action.create(()-> System.out.println("Hello World")).execute(null);
// create normal action
System.out.println(Action.create((Integer i) -> "number: " + i).execute(100));
fabian
  • 80,457
  • 12
  • 86
  • 114
3

Add a static method inside your functional interface

package example;

interface Action<T, U> {
       U execute(T t);
       static  Action<Void,Void> invoke(Runnable runnable){
           return (v) -> {
               runnable.run();
                return null;
            };         
       }
    }

public class Lambda {


    public static void main(String[] args) {

        Action<Void, Void> a = Action.invoke(() -> System.out.println("Do nothing!"));
        Void t = null;
        a.execute(t);
    }

}

Output

Do nothing!
MCHAppy
  • 1,012
  • 9
  • 15
3

Just for reference which functional interface can be used for method reference in cases method throws and/or returns a value.

void notReturnsNotThrows() {};
void notReturnsThrows() throws Exception {}
String returnsNotThrows() { return ""; }
String returnsThrows() throws Exception { return ""; }

{
    Runnable r1 = this::notReturnsNotThrows; //ok
    Runnable r2 = this::notReturnsThrows; //error
    Runnable r3 = this::returnsNotThrows; //ok
    Runnable r4 = this::returnsThrows; //error

    Callable c1 = this::notReturnsNotThrows; //error
    Callable c2 = this::notReturnsThrows; //error
    Callable c3 = this::returnsNotThrows; //ok
    Callable c4 = this::returnsThrows; //ok

}


interface VoidCallableExtendsCallable extends Callable<Void> {
    @Override
    Void call() throws Exception;
}

interface VoidCallable {
    void call() throws Exception;
}

{
    VoidCallableExtendsCallable vcec1 = this::notReturnsNotThrows; //error
    VoidCallableExtendsCallable vcec2 = this::notReturnsThrows; //error
    VoidCallableExtendsCallable vcec3 = this::returnsNotThrows; //error
    VoidCallableExtendsCallable vcec4 = this::returnsThrows; //error

    VoidCallable vc1 = this::notReturnsNotThrows; //ok
    VoidCallable vc2 = this::notReturnsThrows; //ok
    VoidCallable vc3 = this::returnsNotThrows; //ok
    VoidCallable vc4 = this::returnsThrows; //ok
}
SlavaL
  • 41
  • 3