Java 互操作:将@JvmName 应用于接口或抽象中属性的 getter class

Java Interop: Apply @JvmName to getters of properties in interface or abstract class

通常我们可以在kotlin中编写如下代码:

val hasValue : Boolean
    @JvmName("hasValue") get() = true

这将为 Java interop.

生成方法 hasValue() 而不是 getHasValue()

但是,在一个界面中,这给了我一个编译错误:

val hasValue : Boolean
   @JvmName("hasValue") get

抽象中的以下声明也是如此class:

abstract val hasValue : Boolean
    @JvmName("hasValue") get

所以这是我的问题:如何告诉 kotlin 编译器使用 hasValue() 而不是 getHasValue() 作为 kotlin 接口中属性的 getter(和 setter)?

我认为 Kotlin 在 open/override property/function 上使用 @JvmName 有一些限制。禁止在open/override函数上使用@JvmName可以避免在interface/superclass和子类上有不同的jvmName。

在下面的示例中,我尝试使用不同于接口 (hasValue) 的 jvmName (hasValueImpl) 注释覆盖的 属性 getter它给出了编译错误:

'@JvmName' annotation is not applicable to this declaration

interface Abstract {

    @get:JvmName("hasValue")        //Compile error
    val hasValue: Boolean
        get() = false
}

open class Impl : Abstract {

    @get:JvmName("hasValueImpl")    //Compile error
    final override val hasValue: Boolean
        get() = false

    @get:JvmName("hasValue2")       //Compile error if hasValue2 is open
    val hasValue2: Boolean
        get() = false
}

事实证明,这是可能的:

interface Foo {
    val bar: String
        @get:JvmName("getAwesomeBar") get
}

然而,有趣的是这不起作用:

interface Foo {
    @get:JvmName("getAwesomeBar") 
    val bar: String
}

但是,这确实有效:

class Foo {
    val bar: String
        @JvmName("getAwesomeBar") get() = "My bar value"
}

这也行!

class Foo {
    @get:JvmName("getAwesomeBar") 
    val bar: String
        get() = "My bar value"
}

为什么在接口中执行此操作时需要额外的 get: 我无法理解。我确定这是有原因的。

有一个解决方法,请参阅:https://youtrack.jetbrains.com/issue/KT-31420

简单地用注释抑制这个 INAPPLICABLE_JVM_NAME 错误:@Suppress("INAPPLICABLE_JVM_NAME")