Kotlin如何修改构造函数JVM签名以解决平台声明冲突问题
错误原因
你遇到的签名冲突是JVM泛型擦除导致的:List<WebMenuItem>、List<Child>、List<ChildX>、List<ChildXX>这四个带泛型的参数,在编译后泛型类型会被擦除,全部变成List类型,导致四个构造函数编译后的JVM签名完全一致,JVM无法区分不同的构造函数。
解决方案
Kotlin不允许直接给构造函数添加@JvmName注解修改签名,推荐通过伴生对象工厂方法+@JvmName的方式解决冲突,修改后的RowModel代码如下:
class RowModel private constructor( @RowType var type: Int, var isExpanded: Boolean = false ) { companion object{ @IntDef(WEB_MENU, CHILD, CHILDX, CHILDXX) @Retention(AnnotationRetention.SOURCE) annotation class RowType const val WEB_MENU = 1 const val CHILD = 2 const val CHILDX = 3 const val CHILDXX = 4 // 每个工厂方法添加唯一的@JvmName区分JVM签名 @JvmName("createWithWebMenuItem") operator fun invoke( @RowType type: Int, webMenuItem: List<WebMenuItem>, isExpanded: Boolean = false ): RowModel { return RowModel(type, isExpanded).apply { this.webMenuItem = webMenuItem } } @JvmName("createWithChild") operator fun invoke( @RowType type: Int, child: List<Child>, isExpanded: Boolean = false ): RowModel { return RowModel(type, isExpanded).apply { this.child = child } } @JvmName("createWithChildX") operator fun invoke( @RowType type: Int, childX: List<ChildX>, isExpanded: Boolean = false ): RowModel { return RowModel(type, isExpanded).apply { this.childX = childX } } @JvmName("createWithChildXX") operator fun invoke( @RowType type: Int, childXX: List<ChildXX>, isExpanded: Boolean = false ): RowModel { return RowModel(type, isExpanded).apply { this.childXX = childXX } } } lateinit var webMenuItem : List<WebMenuItem> lateinit var child: List<Child> lateinit var childX: List<ChildX> lateinit var childXX: List<ChildXX> }
修改后使用方式和原来的构造函数调用完全一致,不需要改其他地方的调用代码:
// 和之前调用构造函数的写法完全相同 val rowModel = RowModel(RowModel.WEB_MENU, menuList)
替代方案(可选)
如果你不想用工厂方法,也可以给每个构造函数加一个无意义的占位参数区分签名,不过可读性较差,不推荐:
constructor (@RowType type : Int, webMenuItem: List<WebMenuItem>, isExpanded : Boolean = false, placeholder: Int = 0){ this.type = type this.webMenuItem = webMenuItem this.isExpanded = isExpanded } constructor(@RowType type : Int, child: List<Child>, isExpanded : Boolean = false, placeholder: String = ""){ this.type = type this.child = child this.isExpanded = isExpanded } // 剩余两个构造函数同理添加不同默认值的占位参数即可
内容的提问来源于stack exchange,提问作者alpertign
相关产品推荐
相关产品推荐

