Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass Kotlin lambda to Java Supplier argument?

I migrate my project to Kotlin and this phase has a lot of interaction between Java and Kotlin.

In sample below I need to pass a function which implements Java Supplier interface.

java.util.concurrent.CompletableFuture.supplyAsync<Int>({ -> 3 }, executor)

CompletableFuture.supplyAsync({ 3 }, executor)

IntellJ shows error:

Type mismatch.
Required: Supplier<Int!>!
Found: () -> Int

I found a workaround with a helper class but it is not an inline solution.

class Help : Supplier<Int> { fun get() = 3 }
supplyAsync(Help(), executor)

like image 349
Daniil Iaitskov Avatar asked Oct 18 '25 07:10

Daniil Iaitskov


1 Answers

This will work:

CompletableFuture.supplyAsync({ 3 }, executor::execute)

Note that the two signatures are

public static <U> supplyAsync(supplier: Supplier<U>, executor: Executor): CompletableFuture<U>
public static <U> supplyAsync(supplier: () -> U, executor: (Runnable) -> Unit): CompletableFuture<U>

That is, if you want to pass in a lambda, the thing that executes it has to be a method reference (instead of an Executor instance).

Edit: This is documented here, Kotlin allows you to call methods that take SAM (functional interface) parameters with proper Kotlin functions as arguments. However, this is all or nothing. Either you pass a Kotlin function for all SAM parameters, or for none. This explains why the approach you originally took didn't compile. This is not specific methods of the Java API, but instead works for all methods defined on Java classes.

like image 119
Lorenz Avatar answered Oct 19 '25 23:10

Lorenz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!