If I have a Kotlin function
fun f(cb: (Int) -> Unit)
and I want to call f
from Java, I have to do it like:
Unit
in Kotlin is mostly equivalent to void
in Java, however only when the rules of the JVM allow it.
Functional types in Kotlin are represented by interfaces like:
public interface Function1 : Function {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
When you declare (Int) -> Unit
, from Java's point of view this is equivalent to Function
. That's why you have to return a value. To work around this problem, in Java there are two separate interfaces Consumer
and Function
for when you don't have/have a return value.
The Kotlin designers decided to forgo the duplication of functional interfaces and instead rely on compiler "magic". If you declare a lambda in Kotlin, you don't have to return a value because the compiler will insert one for you.
To make your life a little bit easier, you can write a helper method that wraps a Consumer
in a Function1
:
public class FunctionalUtils {
public static Function1 fromConsumer(Consumer callable) {
return t -> {
callable.accept(t);
return Unit.INSTANCE;
};
}
}
Usage:
f(fromConsumer(integer -> doSomething()));
Fun fact: The special handling of Unit
by the Kotlin compiler is the reason you can write code like:
fun foo() {
return Unit
}
or
fun bar() = println("Hello World")
Both methods have return type void
in the generated bytecode but the compiler is smart enough to figure that out and allow you to use return statements/expressions anyway.