如果我有一个Kotlin函数
fun f(cb: (Int) -> Unit)
如果我想从Java中调用f
,我需要这样做:
f(i -> {
dosomething();
return Unit.INSTANCE;
});
看起来非常丑陋。为什么我不能像这样写呢 f(i -> dosomething());
,因为 Kotlin 中的 Unit
相当于 Java 中的 void
?
如果我有一个Kotlin函数
fun f(cb: (Int) -> Unit)
如果我想从Java中调用f
,我需要这样做:
f(i -> {
dosomething();
return Unit.INSTANCE;
});
看起来非常丑陋。为什么我不能像这样写呢 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>
,分别用于没有/有返回值的情况。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
,但编译器足够聪明以解析出这一点,并允许您使用返回语句/表达式。java.util.function.*
只在 API 23 及以上版本可用。请参考此答案 here,并使用 android-retrostreams 来支持 API 24 及以下版本。 - mochadwi我在Kotlin和Java中使用这种方法。你会在Java中看到MyKotlinClass的方法,在Kotlin中你会看到两种方法(类方法+扩展函数)。
MyKotlinClass {
//Method to use in Java, but not restricted to use in Kotlin.
fun f(cb: Consumer<Int>) { //Java8 Consumer, or any custom with the same interface
int i = getYourInt()
cb.accept(i)
}
}
//Extension for Kotlin. It will be used in Kotlin.
fun MyKotlinClass.f(cb: (Int) -> Unit) {
f(Consumer { cb(it) })
}