¿Por qué tengo que devolver Unit.INSTANCE al implementar en Java una function Kotlin que devuelve una Unidad?

Si tengo una function de Kotlin

fun f(cb: (Int) -> Unit) 

y quiero llamar a f desde Java, tengo que hacerlo como:

 f(i -> { dosomething(); return Unit.INSTANCE; }); 

que se ve muy feo ¿Por qué no puedo simplemente escribirlo como f(i -> dosomething()); , dado que la Unit en Kotlin es equivalente a void en Java?

Unit en Kotlin es en su mayoría equivalente a void en Java, pero solo cuando las reglas de la JVM lo permiten.

Los types funcionales en Kotlin están representados por interfaces como:

 public interface Function1<in P1, out R> : Function<R> { /** Invokes the function with the specified argument. */ public operator fun invoke(p1: P1): R } 

Cuando declara (Int) -> Unit , desde el punto de vista de Java esto es equivalente a la Function<Integer, Unit> . Es por eso que debes devolver un valor. Para evitar este problema, en Java hay dos interfaces separadas, Consumer<T> y Function<T, R> para cuando no tiene / tiene un valor de retorno.

Los diseñadores de Kotlin decidieron renunciar a la duplicación de interfaces funcionales y en su lugar confiar en el comstackdor "magic". Si declaras un lambda en Kotlin, no tienes que devolver un valor porque el comstackdor insertá uno para ti.

Para hacer que su vida sea un poco más fácil, puede escribir un método auxiliar que envuelva a un Consumer<T> en una Function1<T, Unit> :

 public class FunctionalUtils { public static <T> Function1<T, Unit> fromConsumer(Consumer<T> callable) { return t -> { callable.accept(t); return Unit.INSTANCE; }; } } 

Uso:

 f(fromConsumer(integer -> doSomething())); 

Dato curioso: el manejo especial de Unit by the Kotlin compiler es la razón por la que puedes escribir código como:

 fun foo() { return Unit } 

o

 fun bar() = println("Hello World") 

Ambos methods tienen el tipo de retorno void en el código de bytes generado, pero el comstackdor es lo suficientemente inteligente como para descubrirlo y le permite usar declaraciones / expresiones de retorno de todos modos.

  • Kotlin Vertx Type Mismatch encontrado Future <Unit> expected Handler <AsyncResult <Void >>
  • Llame al object Kotlin con la delegación de class de Java como método estático
  • ¿Hay una sobrecarga para escribir una biblioteca en Kotlin para Android?
  • Kotlin: No se puede usar GenericTypeIndicator para llamar al getValue de Firebase Database
  • Ejecutando el código de kotlin dentro de un proyecto de Java
  • Acceso a la function de extensión de Kotlin Campo privado de Java
  • Kotlin: atribuye visibilidad al object complementario
  • Anular setter para la variable definida en el constructor pnetworkingeterminado
  • Clases de datos en Kotlin
  • Kotlin: cómo pasar la matriz a la anotación de Java
  • Clase abstracta Kotlin java IllegalAccessError