假设我们在Kotlin中有一个回调:
object Utils {
internal var callback: (() -> Unit)? = null
}
然后我们从Java类调用该回调:
Utils.INSTANCE.setCallback$app_debug(new Function0<Unit>() {
@Override
public Unit invoke() {
return null;
}
});
所以我不得不问:
Unit
转换为void
?setCallback$app_debug
相比,我如何更改回调设置程序的名称?答案 0 :(得分:3)
存在Java命名问题是因为Kotlin编译器实际上为var
生成了getter和setter。尽管可以指示编译器将回调公开为一个字段,但可以使用@JvmField
批注对其进行标记。然后,Java会将其视为常规字段。
我还相信,如果必须从Java调用Kotlin回调,最好稍微改变一下方法。与其将回调声明为callback: (() -> Unit)?
,不如将其设为callback: Runnable?
。
它将稍微改变您设置回调的方式。
object Utils {
@JvmField
internal var callback: Runnable? = null
fun main() {
callback = Runnable { println("Java Runnable") }
}
}
并且将大大改善您从Java与之交互的方式
Utils.callback = (() -> System.out.println("Hello!"));
答案 1 :(得分:3)
由于没有人回答这部分:
与setCallback $ app_debug相比,我如何更改回调设置程序的名称?
不使用internal
。由于Java没有internal
访问限定符,因此它必须在JVM字节码中为public
,但是名称已完全更改,以防止“意外”调用它。如果您想将其保留在Kotlin内部,可以使用@JvmName
:
@get:JvmName("getCallback")
@set:JvmName("setCallback")
internal var callback: (() -> Unit)? = null
答案 2 :(得分:2)
如果函数返回Unit
,则应返回Unit.INSTANCE
对于不同的名称,请尝试使用@JvmName
批注或@JvmField
,然后您将可以作为普通字段而不是自动生成的getter / setter来访问此变量。
答案 3 :(得分:2)
根据您的喜好,可以实现一种专门针对Java接口的解决方法:
// on kotlin side
object Utils {
internal var callback: (() -> Unit)? = null
@JvmStatic
fun setCallback(cb: Runnable) {
callback = { cb }
}
}
// on java side
Utils.setCallback(new Runnable() {
@Override
public void run() {
System.out.println("42");
}
});
Utils.setCallback(() -> {
System.out.println("42");
});
如果符号注释为INSTANCE
,则无需使用@JvmStatic
:
// kotlin
object Utils {
@JvmStatic
internal var callback: (() -> Unit)? = null
}
// java
Utils.setCallback(...)