如何为java调用程序声明返回类型为“void”的Kotlin Lambda?
我有一个完全用Kotlin编写的库,包括它的公共API。现在库的用户使用Java,这里的问题是返回类型为Unit
的Kotlin lambda没有编译为返回类型void
。其效果是,对于有效地void
的方法,Java端始终必须返回Unit.INSTANCE
。这能以某种方式避免吗
例如:
Kotlin Lambda
interface Foo{
fun bar(x:(String)->Unit)
}
Java调用
public void call(){
foo.bar(this::processString)
}
//the return type should rather be void instead of Unit
public Unit processString(String s){
return Unit.INSTANCE
// ^^ implementations should not be forced to return anything
}
是否可以以不同的方式声明Kotlin Lambda,以便编译器生成void
返回类型
另见How to declare a Kotlin function with return type 'void' for a java caller?
# 1 楼答案
如果Java互操作是最重要的,我要么直接使用Java功能接口(即
Consumer
、Supplier
,等等),要么现在就创建自定义Kotlin functional interfaces。同时Kotlin更好地处理功能接口Java变体:
带有自定义
Consumer
的Kotlin变体:用法同上。也许今天有一种更简单的方法来处理像
(String) -> Unit
这样的事情,但是我还不知道(或者觉得还没有必要研究它;-)。Ilya在评论中提到的编译器注释可能是解决这个问题的一种方法2018年12月,我写道:我没有一个真正的答案,但我将分享我在这种情况下做了什么,我需要从Java访问这样的Kotlin代码(或者我想到了什么)
基本上,这取决于你真正想要触摸/增强哪一面,以获得你所需要的
增强Kotlin代码以支持Java等价物:
这有一些缺点:
Consumer
-方法也可以从Kotlin中看到,因此也可以从那里调用。不用说,您需要复制接口中的所有函数,因此整个Kotlin接口变得更加臃肿。但是:它从两个方面都起作用,就像你期望的那样。Java调用Consumer
-variant,Kotlin调用(String) -> Unit
-variant。。。希望如此;-)实际上只是演示一些通话:话虽如此,另一个变体是添加帮助器方法,这些方法实际上有助于从Java更轻松地调用Kotlin函数,例如:
这可能永远不会从Kotlin调用(因为将backticks与$组合在一起编写已经够麻烦了),或者如果您不想让Kotlin代码膨胀,只需将这样一个方法添加到Java中,但它看起来并没有那么简单:
对这两个方法的调用看起来都一样:
对于我需要解决的问题,我只返回了
Unit.INSTANCE
或null
,但是如果我有更多的方法可以调用,我可能会选择第二种($(...)
)方法。在最好的情况下,我只需要提供(生成?;-))等价物一次,并在几个项目中使用它们,而仅为Java提供接口中的default
变体可能需要更多的工作,甚至可能会让一些人感到困惑最后:不。。。我不知道有哪个选项可以让你在Kotlin的
Unit
返回的功能接口中有void
这样的功能接口(/consumers)# 2 楼答案
实际上,没有必要在罗兰的答案中添加
$
符号只需一个方法名,就可以直接在kotlin和java中获得良好的编码体验
以下是您需要做的事情(实际上与罗兰的答案相同,但我的示例代码供您参考):
javac知道引用方法的返回类型不是
Unit
,因此它将调用Consumer$
方法kotlin编译器不会检查
FunctionX
的继承,因此它将调用(String)->Unit
方法