在 Java 中使用 Kotlin Value 类

Caf*_*eek 4 java kotlin value-class

我们有两个项目,kotlin 项目发布了一个由 java 导入的包。

在 kotlin 中,是一个像这样的值类

@JvmInline
value class CountryId(private val id: UUID) {
    override fun toString(): String = id.toString()
    companion object { fun empty(): CountryId = CountryId(EMPTY_UUID) }
}
Run Code Online (Sandbox Code Playgroud)

在java中,我们看不到构造函数,也看不到实际实例化这个类。我还尝试在 Kotlin 中创建一个工厂来创建它们

class IdentifierFactory 
{
    companion object {
        fun buildString(): String {
            return "hello"
        }

        fun buildCountry(): CountryId {
            return CountryId.empty()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在java中,我可以调用IdentifierFactory.Companion.buildString()它并且它会工作,但它IdentifierFactory.Companion.buildCountry()甚至不存在。

Java 的 Value 类真的这么糟糕吗?

附:我也尝试过@JvmStatic,但没有成功

pps。如果我从java端反编译kotlin字节码,并得到一个CountryId.decompiled.java,这就是构造函数的样子

// $FF: synthetic method
private CountryId(UUID id) {
    Intrinsics.checkNotNullParameter(id, "id");
    super();
    this.id = id;
}
Run Code Online (Sandbox Code Playgroud)

点赞。Kotlin 1.5.21 和 Java 12

Jof*_*rey 8

Java 的 Value 类真的这么糟糕吗?

值类是 Kotlin 的一项功能。它们基本上是糖,以允许更多的类型安全(在 Kotlin 中!),同时通过拆箱内部值来减少分配。类存在于字节码中的事实CountryId主要是因为某些实例在某些情况下需要装箱(当用作泛型类型、超类型或可空类型时 - 简而言之,有点像基元)。但从技术上讲,它并不是真正适合从 Java 方面使用。

在java中,我可以调用 IdentifierFactory.Companion.buildString() 并且它会工作,但 IdentifierFactory.Companion.buildCountry() 甚至不存在。

默认情况下,签名中带有值类的函数故意在 Java 中不可见,以避免 Java 中重载的奇怪问题。这是通过名称修改来完成的。您可以通过使用 Kotlin 端工厂函数上的注释来覆盖 Java 方法的名称@JvmName,以使其在 Java 中可见:

@JvmName("buildCountryUUID") // prevents mangling due to value class
fun buildCountry(): CountryId {
    return CountryId.empty()
}
Run Code Online (Sandbox Code Playgroud)

然后它可以在 Java 端访问并返回一个UUID(内联值):

UUID uuid = IdentifierFactory.Companion.buildCountryUUID();
Run Code Online (Sandbox Code Playgroud)

理想情况下,我只希望构造函数能够工作而不是使用工厂

我从评论中意识到您是在CountryId从 Java 创建实际实例之后。使用CountryIdJava 的构造函数对我来说效果很好:

CountryId country = new CountryId(UUID.randomUUID());
Run Code Online (Sandbox Code Playgroud)

但我不确定这是怎么可能的,因为生成的构造函数在字节码中是私有的......