类型擦除对Java调用Kotlin的影响
@JvmName:
扩展方法相关:
先来定义一个扩展方法:
好,接下来再来定义一个扩展函数:
此时报错了。。看一下错误提示:
其中给的提示有点奇怪,第一个是很明显咱们的扩展函数木有接收参数嘛,为啥提示JVM签名是接收一个List参数呢?其实这里就涉及到了扩展函数的语义了,对于扩展函数来说,其实是将被扩展的那个类作为扩展函数的第一个参数传进去的,为啥呢?因为Java中是不支持扩展函数的;第二个咱们声明不是已经定义了不同的泛型嘛,为啥提示这俩方法签名冲突了呢?这里需要注意了在Java中的泛型其实是一个假的泛型,在被编译成了字节码文件中这些泛型的类型都被去掉了,用一个专业术语来描述这个“去掉”就叫“类型擦除”, 然后最终在取值的时候再根据我们定义的泛型类型会向下强制进行类型转换,所以很明显我们定义的这俩方法如果在泛型类型都被擦除之后不就很明显是定义了2个一模一样类型的函数了么,如下:
那。。如果就想将这俩函数定义在一个文件中,其实也是有办法的,需要用到Kotlin注解了,如下:
接下来咱们新建一个Java类来调用一下它:
那如果在Kotlin直接调用呢,其实就简单很多了,如下:
属性相关:
我们知道对于Kotlin中如果定义了一个属性则会自动会生成它的getter和setter,那如果我们手动也定义了一个跟getter或setter方法同名的方法,那是不是就会有冲突的可能,下面来演示一下这种情况:
看提示很明显就是冲突了嘛:
同样的,可以用注解来解冲突,如下:
然后再定义一个Java文件来访问一下:
那如果在Kotlin中去调用呢?
可见Kotlin写的代码在Kotlin调用是要简化很多的。
@JvmOverloads:
我们知道在Kotlin中的方法中是可以支持默认值的,但是在Java中很明显是不支持的,那如何做到两者兼容呢?下面演示一下:
然后新建一个Java来调用一下:
此时就可以用注解来改变一下:
再回到Java中,看此时的构造:
此时也可以传2个参数:
此时就比较理解了,其@JvmOverloads注解发挥了作用,它会给拥有默认参数的构造方法声明重载的版本,回到咱们这个程序来说就会生成如下的重载:
这样就成功的将Kotlin允许有默认参数的行为给适配到Java层了。