Java中有Class,而Kotlin则有它的KClass,说说二者的区别和联系。
1. Java Class
Java中的Class是一个final修饰的类,只有一个私有的构造方法,
1 | public final class Class<T> { |
根据方法说明可以知道,这个构造方法是给JVM调用的,JVM在加载类的时候会创建对应的Class实例,存放在方法区,一个类只会有一个Class实例,所以下面这个例子中,c1和c2是一样的。
1 | // Java |
Class类中的方法和成员变量相当之多,但基本都关于Class本身的数据相关,比如获取成员函数、获取成员变量,等等。
2. Kotlin KClass
与Java Class不同的是,KClass是一个接口,根据接口说明,::class
可以获取到KClass的实例,这个接口中同样也是声明了一些和类有关的变量,比如类的名字,类的成员等等
1 | /** |
KClass有一个实现类,名字是ClassReference,根据名字可以看出,这个类就是参考的Class,通过将Class实例作为构造参数传入,相关字段均通过class实例获取
1 | public class ClassReference(override val jClass: Class<*>) : KClass |
通过Kotlin可扩展的语言自身特性,为KClass扩展了几个属性,这些属性在JvmClassMapping.kt中
1 | public val <T> KClass<T>.java: Class<T> |
前两个属性还挺有趣,Class.kotlin获取KClass,KClass.javaClass获取Class,真是你中有我,我中有你,.完java再.kotlin,能这么一直循环玩下去。后两个属性的区别是,如果本身不是原始类型,那么javaPrimitiveType会返回null。
最后一个javaClass,已经弃用了,上面写了,让使用java属性,那就不管它就好了
3. 总结
Java的Class我们是很熟识的了,容易造成混乱的,就是它和KClass的关联,二者可以互相获取
- 获取KClass,按照文档里写的,直接取class属性,在实例和在类上调用,获得的结果是一样的
1
2
3
4
5
6
7// 1. 直接获取
class Person {}
val kc1 = Person::class
val kc2 = Person()::class
// 2. 从Class获取
val kClass = Person().javaClass.kotlin - 获取Class,主要通过扩展属性
1
2
3
4
5// 1. 从实例获取
val jClass = Person().javaClass
// 2. 从KClass获取
val jClass = Person::class.java