2021-07-09
文章目录
以下基于kotlin 1.5.20 版本
1. kotlin中的属性与方法
在kotlin中的公共属性默认会被编译成为相应的getter
与setter
方法在java中可以去被调用。
在编译后的JVM字节码中,公共属性被编译成指定的getter
与setter
签名的方法,所以在java中使用该属性是通过方法的方式进行使用的,而不是字段。
//在java中将被编译成getName()与setName(String)的方法签名
var name:String=""
1.1. JVM签名冲突
由于kotlin编译时会有这样的机制,所以以下代码就会出现问题。
interface IStudent{
//定义了一个只读属性name
val name:String
//定义了一个getName的方法
//此处会报错
fun getName():String
}
此处会报错 Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;)
由于只读属性name
最终会被编译成String getName()
这样的方法签名,所以实际上与下面定义的方法已经产生了签名冲突了。
val name:String -> 编译成:String getName()
fun getName():String -> 编译成:String getName()
//这里编译后已经存在相同签名的方法了
对于这样的情况,意味着有以下限制:
- 在kotlin中,同一个类/接口使用了只读属性(val)则不能定义相应的
getter
方法;使用了可读写属性(var)则不能定义相应的getter
与setter
方法 - 在kotlin中,子类继承的父类/接口也不能出现冲突的属性或方法
- 同理在java与kotlin混合使用的互操作情况下,不管在java中继承kotlin的类/接口,还是反过来,都双方都不允许出现有冲突的属性或方法
类似问题参考:
How to overcome “same JVM signature” error when implementing a Java interface?
1.2. 可能的解决方案
以上的问题根本原因已经提及了,就是因为最终的签名冲突了。所以只要能解决签名的问题,那么就不会存在此问题了。
1.2.1. 修改签名
幸运的是,在kotlin中允许通过注解修改编译后的方法名。