java - 更改 kotlin 扩展函数接收器 JVM 名称

标签 java kotlin kotlin-interop java-interop

这是一个普遍的问题。 假设我有一个用 kotlin 编写的扩展函数,它将 DP 转换为 PX 并返回一个 NonNull Int

fun Int.toPx() {  /** implementation */ }

java中的函数看起来像这样

public int toPx(int $receiver) {  /** implementation */ }

在我看来,$receiver 让 Java 互操作感觉生成和不受欢迎。

我知道您可以使用 @JvmName 注释和一些组合,如 @file:JvmName 来更改 java 中的名称。

当我尝试将 @JvmNamereceiver 站点目标一起使用时,它会显示

"此注解不适用于目标类型用法,使用站点目标@receiver"

有没有办法克服这个问题并更改接收者的名称,如果没有,最好的选择是什么。

最佳答案

@JvmName 只能应用于文件的函数、属性访问器和顶级包外观。不支持参数名称。

基本上,您可以定义两个函数,一个带简单参数,另一个带接收器:

fun toPx(value: Int) { /* implementation */ }

fun Int.toPx() = toPx(this)

但是,不出所料,这不会编译,因为这两个函数将具有相同的 JVM 签名。因此,为了消除歧义,请将 @JvmName("...") 添加到扩展名中,并(可选)将扩展名标记为 inline:

fun toPx(value: Int) { /* implementation */ }

@JvmName("toPxExtension") @Suppress("nothing_to_inline")
inline fun Int.toPx() = toPx(this)

要对Java隐藏扩展功能,您还可以annotate it with @JvmSynthetic .

此解决方案的缺点是顶级函数 toPx 泄漏到查看包的文件的 IDE 完成范围内。

关于java - 更改 kotlin 扩展函数接收器 JVM 名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47775870/

相关文章:

android - Kotlin - 在运行函数之前等待多个 LiveData 被观察

kotlin - 找到Kotlin Vertx类型不匹配Future <Unit>预期的Handler <AsyncResult <Void >>

kotlin - 谁能在这里详细解释 Kotlin/Native spinner 应用程序项目结构?还有关于不同模块如何工作的细节

groovy - 带接收器的 Kotlin 函数参数,从 Groovy 调用

java - 如何在 Swing 中从多个 JList 中仅选择一项

java - Spring BeanFactory加载和卸载

android - 在 Kotlin Multiplatform 上复制到剪贴板

java - Android 文本转语音抛出 ActivityNotFoundException

java - Android 随机数 llegalArgumentException : n <= 0: 0

Kotlin - 向 ActionBar 添加操作按钮