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:
f(i -> { dosomething(); return Unit.INSTANCE; });
which looks very ugly. Why can't I just write it like f(i -> dosomething());
, since Unit
in Kotlin is equivalent to void
in Java?
Unit in Kotlin corresponds to the void in Java. Like void, Unit is the return type of any function that does not return any meaningful value, and it is optional to mention the Unit as the return type. But unlike void, Unit is a real class (Singleton) with only one instance.
The return keyword already is optional for functions* in Kotlin.
The Nothing type has no values. If a function has return type Nothing , then it cannot return normally. It either has to throw an exception, or enter an infinite loop. Code that follows a call to a function with return type Nothing will be marked as unreachable by the Kotlin compiler.
To return values, we use the return keyword. In the example, we have two square functions. When a funcion has a body enclosed by curly brackets, it returns a value using the return keyword. The return keyword is not used for functions with expression bodies.
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<in P1, out R> : Function<R> { /** 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<Integer, Unit>
. That's why you have to return a value. To work around this problem, in Java there are two separate interfaces Consumer<T>
and Function<T, R>
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<T>
in a Function1<T, Unit>
:
public class FunctionalUtils { public static <T> Function1<T, Unit> fromConsumer(Consumer<T> 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With