为什么在Java中实现一个返回Unit的Kotlin函数时,必须返回Unit.INSTANCE?
如果我有Kotlin功能
fun f(cb: (Int) -> Unit)
我想从Java调用f
,我必须这样做:
f(i -> { dosomething(); return Unit.INSTANCE; });
这看起来很丑陋。 为什么我不能像f(i -> dosomething());
那样写它f(i -> dosomething());
,因为Kotlin中的Unit
相当于Java中的void
?
Kotlin中的Unit
大多相当于Java中的void
,但是只有当JVM的规则允许时。
Kotlin中的函数类型由以下接口表示:
public interface Function1<in P1, out R> : Function<R> { /** Invokes the function with the specified argument. */ public operator fun invoke(p1: P1): R }
当你声明(Int) -> Unit
,从Java的角度来看,这相当于Function<Integer, Unit>
。 这就是为什么你必须返回一个值。 要解决这个问题,在Java中有两个独立的接口Consumer<T>
和Function<T, R>
,当你没有/有一个返回值时。
Kotlin设计师决定放弃功能接口的重复,而是依靠编译器“魔术”。 如果你在Kotlin中声明一个lambda,你不必返回一个值,因为编译器会为你插入一个。
为了让你的生活变得更轻松一点,你可以编写一个辅助方法,将一个Consumer<T>
包装在Function1<T, Unit>
:
public class FunctionalUtils { public static <T> Function1<T, Unit> fromConsumer(Consumer<T> callable) { return t -> { callable.accept(t); return Unit.INSTANCE; }; } }
用法:
f(fromConsumer(integer -> doSomething()));
有趣的事实:Kotlin编译器对Unit
的特殊处理是你可以编写如下代码的原因:
fun foo() { return Unit }
要么
fun bar() = println("Hello World")
这两种方法在生成的字节码中都有返回类型void
,但是编译器足够聪明,可以解决这个问题,并允许您使用return语句/表达式。
- Android Studio Kotlin dataSnapshot.getValue错误
- 为什么Kotlin的字符串插值在Java中串联字符串?
- 当使用Java / Kotlin进行编程时,建议使用尾递归还是迭代版本? 性能有什么不同?
- 空合并操作符的替代方法
- 默认值@ProjectedPayload / ProjectingJackson2HttpMessageConverter
- 如何将一个整数数组传递给期望`Array <T>`的方法?
- 在没有JVM支持的情况下,如何在JVM语言中实现协程?
- 错误:在使用Kotlin编译Java代码时,-source 1.3中不支持generics
- 如何防止杰克逊(德)序列化某些属性?