Java 8 lambda Void argument
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?
Solution 1:
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.
Solution 2:
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
Solution 3:
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"));
Solution 4:
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.
Solution 5:
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!");