373

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?

6
  • 2
    Take a look at stackoverflow.com/questions/14319787/… Commented Apr 29, 2015 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!"); Commented Apr 29, 2015 at 13:49
  • 1
    @BobTheBuilder I don't want to use a Consumer as suggested in that post. Commented Apr 29, 2015 at 13:50
  • 2
    Matt's answer makes the types work, but what does the caller do when it gets a null return value? Commented Apr 29, 2015 at 15:06
  • 8
    You could cross fingers and hope that suggestions 2 & 3 in this post get accepted for Java 9! Commented Apr 29, 2015 at 15:23

10 Answers 10

942

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.

Sign up to request clarification or add additional context in comments.

8 Comments

As an example I did this to wrap "void" return call : public static void wrapCall(Runnable r) { r.run(); }. Thanks
Does not help if it must throw a checked exception, unfortunately.
Consumer allows only one input parameter
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
Is there anything like Callable (which throws an exception in its call() method) but does require any return value?
|
517

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

3 Comments

Don't forget BiConsumer: x, y -> ()!
I think Java lacks of RunnableThrowingException () -> () throws ex... (see stackoverflow.com/a/53398040/363573)
Tysvm for this table. I have reified and extended it into a Google Sheet document I've shared here: docs.google.com/spreadsheets/d/…
139

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"));

4 Comments

This is the cleanest workaround you could get, IMO, so +1 (or with a static method in the interface itself)
Konstantin Yovkov's solution below (with @FunctionalInterface) is a better solution, because it does not involve generics and does not require extra code.
@uthomas Sorry, I don't see an answer involving @FunctionalInterface. He merely says, that it's not possible to extend it...
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.
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.

2 Comments

The problem is that your Something function cannot be a subtype of my Action type, and I can't have two different types.
Techmically he can, but he said he wants to avoid it. :)
34

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!");

3 Comments

Where is this Action<Void,Void> coming from? Neither the Swing nor the JAX-WX Action interfaces have such an generic interface?
@luis.espinal: Action<T, U> is declared in the question.....
Hahaha, how the heck did I miss that? Thanks!
8

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

Comments

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.

Comments

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));

Comments

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!

Comments

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
}

1 Comment

Please add some more context. This looks interesting, but its meaning is not immediately obvious.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.