When you pass a Kotlin lambda or SAM-like callback to Kotlin from Java, when must Java code return Unit.INSTANCE, and why?
answer
- () -> Unit ⇒ Function0<Unit>, invoke returns Unit
- Java must return Unit.INSTANCE for function-type callbacks
- fun interface with Unit method ⇒ void ⇒ no return needed
- Generics can't hold void ⇒ Unit fills the slot
- Prefer fun interface for Java-friendly APIs
basics
~10 sIf the Kotlin API takes a function type like () -> Unit, Java must implement Kotlin's Function interface and explicitly return Unit.INSTANCE; because the function's generic return type is Unit, not void.
solid answer
~40 sKotlin function types compile to `kotlin.jvm.functions.FunctionN<…, R>` interfaces. A `() -> Unit` parameter is `Function0<Unit>`, whose `invoke()` returns `Unit`. From Java you can supply a lambda only because Java treats `Function0` as a functional interface, but since `R = Unit` is a **reference type** (generics can't use `void`), the lambda body must end with `return Unit.INSTANCE;`. By contrast, if the Kotlin API is declared as a **Java SAM interface** (a real `interface` with a single `void` method), Java just implements that void method normally — no Unit. The distinction: Kotlin **function types** carry `Unit` as a generic argument; **Java functional interfaces** with `void` methods don't. Use Kotlin's `Unit.INSTANCE` (or a helper) to satisfy the former.
code
kotlin · 8 lines// Kotlin API designs:
fun onClickFn(cb: () -> Unit) { cb() } // Function0<Unit>
fun interface Click { fun handle() } // void handle()
fun onClickSam(cb: Click) { cb.handle() }
// Java callers:
// onClickFn(() -> { foo(); return Unit.INSTANCE; }); // must return INSTANCE
// onClickSam(() -> foo()); // clean void lambdago deeper
Recognizes that some Kotlin callbacks need return Unit.INSTANCE; in Java.
Explains the FunctionN<Unit> mechanism and why generics force a Unit value.
Contrasts function types vs fun interface/SAM lowering and advises designing Java-friendly Kotlin APIs.
Weighs API ergonomics, binary-compatibility, and SAM-conversion rules when designing cross-language callback surfaces.
## The two callback shapes When Java code passes a callback into Kotlin, there are two distinct situations: ### 1. Kotlin **function type** parameter — `(...) -> Unit` Kotlin lowers function types to the synthetic interfaces `kotlin.jvm.functions.Function0<R>`, `Function1<P1,R>`, …, `FunctionN`. A parameter typed `() -> Unit` is `Function0<Unit>`. Its single method is: ``` R invoke(); // here R = Unit ``` Because JVM **generics are reference-type only**, `R` can't be `void`; Kotlin uses `Unit`. So Java must return the singleton: ```java kotlinApi.onClick(() -> { System.out.println("clicked"); return kotlin.Unit.INSTANCE; // required: invoke() returns Unit }); ``` Forgetting the `return Unit.INSTANCE;` is a compile error from Java. ### 2. Java/Kotlin **SAM interface** with a `void` method If the API instead declares a normal interface: ```kotlin fun interface OnClick { fun handle() } // handle(): Unit ⇒ void ``` then `handle()` compiles to a `void` method, and Java implements it with no return: ```java kotlinApi.onClick(() -> System.out.println("clicked")); ``` Kotlin's `fun interface` (functional interface) members that return `Unit` become `void`, so the Java lambda is clean. ## Why the difference - **Function types** (`() -> Unit`) keep `Unit` as a **generic type argument** of `FunctionN`, which can't be `void` ⇒ `Unit.INSTANCE` required. - **SAM/`fun interface`** methods are ordinary methods whose `Unit` return lowers to **`void`** ⇒ nothing to return. ## Practical guidance When designing Kotlin APIs intended for Java consumers, prefer a `fun interface` (SAM) over a raw function type so Java callers don't have to write `return Unit.INSTANCE;`. The `@JvmName`/SAM-conversion ergonomics are better. ## Summary - `() -> Unit` ⇒ `Function0<Unit>`, Java must `return Unit.INSTANCE;`. - `fun interface { fun f() }` ⇒ `void f()`, Java returns nothing. - Root cause: generic `Unit` arg vs. a plain `void` method.
- What package/class holds the function-type interfaces?`kotlin.jvm.functions.Function0`..`Function22` (and `FunctionN` for higher arities); they live in the Kotlin stdlib.
- How would you make a () -> Unit Kotlin API more Java-friendly?Expose a `fun interface` (SAM) whose method returns Unit; it compiles to a void method, so Java lambdas need no `return Unit.INSTANCE;`.
saying these in an interview costs you the question
- Thinking a () -> Unit lambda can be implemented in Java without returning Unit.INSTANCE
- Confusing Kotlin function types with Java functional interfaces
- Claiming Function0<Unit>.invoke() returns void
- Not knowing fun interface members returning Unit become void