Search code examples
javakotlingenericssyntaxcompletable-future

Kotlin Syntax for whenCompleteAsync(BiConsumer,Executor)


How do I implement a function in Kotlin for below method signature. I am facing issues getting the syntax correct.

public CompletableFuture<T> whenCompleteAsync(
        BiConsumer<? super T, ? super Throwable> action, Executor executor)

Solution

  • The analogue to Java's BiConsumer<? super T, ? super Throwable> generic type would be written in Kotlin as BiConsumer<in T, in Throwable>. The in keyword indicates that the generic type T is contravariant.

    This is how whenCompleteAsync function could be implemented in Kotlin using such method signature:

    fun <T> whenCompleteAsync(
        action: BiConsumer<in T, in Throwable>, 
        executor: Executor
    ): CompletableFuture<T> {
        val future = CompletableFuture<T>()
    
        executor.execute {
            try {
                val result = future.get()
                action.accept(result, null)
            } catch (e: Throwable) {
                action.accept(null, e)
            }
        }
    
        return future
    }
    

    Usage:

    val future = whenCompleteAsync(
        BiConsumer { result, ex ->
            if (ex != null) {
                // Handle exception
            } else {
                // Handle result
            }
        },
        Executors.newSingleThreadExecutor()
    )
    

    In Kotlin no need to use BiConsumer interface unless it is required exactly for some reason. Instead it is possible to use Kotlin function with two arguments and simplify the example:

    fun <T> whenCompleteAsync(
        action: (T?, Throwable?) -> Unit,
        executor: Executor
    ): CompletableFuture<T> {
        val future = CompletableFuture<T>()
    
        executor.execute {
            try {
                val result = future.get()
                action(result, null)
            } catch (e: Throwable) {
                action(null, e)
            }
        }
    
        return future
    }
    
    val future = whenCompleteAsync(
        { result, ex ->
            if (ex != null) {
                // Handle exception
            } else {
                // Handle result
            }
        },
        Executors.newSingleThreadExecutor()
    )