从Java调用Kotlin高阶函数?

时间:2020-04-02 09:40:58

标签: java android kotlin

假设我们在Kotlin中有一个回调:

object Utils {
internal var callback: (() -> Unit)? = null
}

然后我们从Java类调用该回调:

Utils.INSTANCE.setCallback$app_debug(new Function0<Unit>() {
        @Override
        public Unit invoke() {
            return null;
       }
    });

所以我不得不问:

  1. 由于被迫返回值,我如何将Unit转换为void
  2. setCallback$app_debug相比,我如何更改回调设置程序的名称?

4 个答案:

答案 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(...)
相关问题