kotlin 中::class 、class.java、javaClass、javaClass.kotlin区别

Kotlin的类

class Person{

var name: String =""

var age:Int=0

companion object{

    }

}

java类

public class Man{

}

要知道获取的到底是什么,可以利用andorid stuido的类型提示,一目了然。

第二张

引申

在Java中使用Class很常见的就是,xxx类.class,比如我们在startActivity的时候startActivity(new Intent(this, OtherActivity.class));这里接收的就是CLass cls参数。

那么在java中获取Class的方法有哪些呢?

1、Classc=person.getClass();//对象获取

2、Classcc=Person.class;//类获取

而我们来看看kotlin

//对象获取

person.javaClass// javaClass

person::class.java// javaClass

//类获取

Person::class//kClass

person.javaClass.kotlin// kClass

(Person::classasAny).javaClass//javaClass

Person::class.java// javaClass

哇,这么多种,他们是不是一样的,有没有什么区别?

log看看他们到底是不是相同的Class

println(person.javaClass == person::class.java)//true

println(person.javaClass == Person::class.java)//true

println(person::class.java == Person::class.java)//true

//person.javaClass == person::class.java == Person::class.java

println(person.javaClass == Person::class)//false

println(person.javaClass.kotlin == Person::class)//true

println(person::class==Person::class)//true

从log来看,person.javaClass == person::class.java == Person::class.java

三者是相同的。但是person.javaClass == Person::class却是不同的。为什么呢?

原因是在kotlin中的Class与Java不同,kotlin中有一个自己的Class叫做KClass,person::class 和Person::class都是获取kotlin的KClass,所以println(person::class == Person::class) 为true。

我们可以从kotlin的KClass获取到java的Class,person::class.java就是如此,先获取到kotlin的KClass然后再获取javaClass。

object/class->kClass->Class

同样也可以通过java的Class获取kotlin的KClass,person.javaClass.kotlin就是先获取javaClass然后再获取kotlin的KClass

object/class->Class->KClass

那么KClass都有些什么用呢?Find Usages 可以看到

几乎多数跟Reflect相关,而用的最多的也是在KClasses里面

KClasses扩展了许多跟反射相关的方法,算的上是kotlin的反射中类主力输出。

举个例子

我们要把一个类的所有字段通过反射给打印出来,调用java的方法来实现是这样

println (Person::class.java.declaredFields.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

我们通过Person::class拿到KClass,然后.java拿到java的Class,再获取declaredFields,最后通过map,然后把获取的Field获取到值打印出来

问题

而使用kotlin,我们还有别的做法

println (Person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

通过Person::class拿到KClass,直接调用KClass的memberProperties来拿到KProperty的Collection集合,然后进行操作。当然,这里KProperty也是kotlin的反射类中的,也类似于Java的Field。

那么既然可以这样,理论上这样也应该是可以的

//person是对象不是Person类

println (person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

这下却出错了,真的奇怪!

Error:(73,31)Out-projectedtype'KProperty1' prohibits the use of 'public abstract fun get(receiver:T):Rdefined in kotlin.reflect.KProperty1'

为什么会这样?

查看it发现

kotlin的property的Person为out逆变的,R只能作为输出,不能作为get的参数传入,所报错了。

这里的kotlin泛型还是有点小坑的需要你踩一踩,网上有一篇文章解释说明了一番

那么怎么改呢?三种办法:

第一种:

//扩展KProperty的get方法为getUnsafed,其实就是去掉了out

funKProperty1.getUnsafed(receiver:Any): R {

returnget(receiverasT)

    }

//然后

println(person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.getUnsafed(person)}"

}.joinToString(","))

第二种:

//强转一下

println(person::class.memberProperties.map {

it.isAccessible =true

itasKProperty1

"${it.name}:${it.get(person)}"

}.joinToString(","))

第三种:

//这一种就涉及到kotlin中的获取KClass的方式, 先获取java的Class再获取kotlin的KClass

//神奇的是,这种获取到的it的类型没有out,而是我们期望的 KProperty1

println(person.javaClass.kotlin.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

摘自:链接:

举个例子

我们要把一个类的所有字段通过反射给打印出来,调用java的方法来实现是这样

println (Person::class.java.declaredFields.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

我们通过Person::class拿到KClass,然后.java拿到java的Class,再获取declaredFields,最后通过map,然后把获取的Field获取到值打印出来

问题

而使用kotlin,我们还有别的做法

println (Person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

通过Person::class拿到KClass,直接调用KClass的memberProperties来拿到KProperty的Collection集合,然后进行操作。当然,这里KProperty也是kotlin的反射类中的,也类似于Java的Field。

那么既然可以这样,理论上这样也应该是可以的

//person是对象不是Person类

println (person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

这下却出错了,真的奇怪!

Error:(73,31)Out-projectedtype'KProperty1' prohibits the use of 'public abstract fun get(receiver:T):Rdefined in kotlin.reflect.KProperty1'

为什么会这样?

查看it发现

kotlin的property的Person为out逆变的,R只能作为输出,不能作为get的参数传入,所报错了。

这里的kotlin泛型还是有点小坑的需要你踩一踩,网上有一篇文章解释说明了一番

那么怎么改呢?三种办法:

第一种:

//扩展KProperty的get方法为getUnsafed,其实就是去掉了out

funKProperty1.getUnsafed(receiver:Any): R {

returnget(receiverasT)

    }

//然后

println(person::class.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.getUnsafed(person)}"

}.joinToString(","))

第二种:

//强转一下

println(person::class.memberProperties.map {

it.isAccessible =true

itasKProperty1

"${it.name}:${it.get(person)}"

}.joinToString(","))

第三种:

//这一种就涉及到kotlin中的获取KClass的方式, 先获取java的Class再获取kotlin的KClass

//神奇的是,这种获取到的it的类型没有out,而是我们期望的 KProperty1

println(person.javaClass.kotlin.memberProperties.map {

it.isAccessible =true

"${it.name}:${it.get(person)}"

}.joinToString(","))

摘自:链接:

https://blog.csdn.net/jdsjlzx/article/details/105327842

https://www.jianshu.com/p/a900ee71ae7f

你可能感兴趣的:(kotlin 中::class 、class.java、javaClass、javaClass.kotlin区别)