You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带值类的二级构造函数与主构造函数JVM签名冲突问题求助

带值类的二级构造函数与主构造函数JVM签名冲突问题求助

兄弟我太懂你这个烦恼了!用值类做类型安全本来是件省心的事,结果碰到JVM签名冲突的坑,常用的注解还都帮不上忙,确实头疼。

先给你捋清楚问题根源:你用的@JvmInline值类在JVM层面会被自动脱箱,所以接收PersonId的二级构造,最终生成的JVM参数还是Int,和主构造的(Int)签名完全一致,这就导致了平台声明冲突。而且你说的没错,@JvmSynthetic不能用在构造函数上,@JvmName也没法修改构造函数的签名,这俩注解确实派不上用场。

下面给你两个可行的解决方案,其中一个能满足你保留二级构造的需求:

变通方案:利用vararg规避签名冲突

这个方法有点取巧,但完美符合你想用二级构造的要求。思路是把二级构造的参数转成vararg数组形式,让JVM生成完全不同的签名(数组类型vs单个Int),从而避开冲突:

@JvmInline
value class PersonId(val id: Int)

data class PersonJson(val id: Int) {
    // 通过vararg数组展开调用主构造,规避JVM签名冲突
    constructor(id: PersonId) : this(*intArrayOf(id.id))
}

在Kotlin里调用完全正常,PersonJson(PersonId(123))和PersonJson(123)都能正常工作,而且因为你不需要对Java可见,Java那边也不会用到这些构造函数,完全不影响你的使用场景。

备选方案:伴生对象工厂方法(规范写法)

如果觉得上面的vararg写法有点别扭,那伴生对象的工厂方法是最规范的解决方式,代码可读性也更高:

@JvmInline
value class PersonId(val id: Int)

data class PersonJson(val id: Int) {
    companion object {
        fun fromPersonId(id: PersonId) = PersonJson(id.id)
    }
}

调用的时候用PersonJson.fromPersonId(PersonId(123)),虽然多了个方法名,但完全没有签名冲突的问题,代码逻辑也更清晰。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 14:54:35