这个反射还要再学一遍
内容
1.反射的基本使用
2.使用KClass创建对象
3.利用反射调用方法
4.利用反射调用属性
5.反射顶层方法
一.反射的基本使用
Java中的字节码文件是 .class
kotlin中的字节码文件时 .KClass
import kotlin.reflect.full.*
//反射
//在程序运行过程中动态地调用类的属性和方法
fun main() {
//如何获取字节码文件类型
//1.只知道这个类型
val clz = Person::class
//2.已经有对象了
val xw = Person()
val clz2 = xw.javaClass.kotlin
//可以通过class对象获取类的详细信息
println(clz.simpleName)//类名
println(clz.qualifiedName)//全类名 有详细包路径,如 fanshe.Person
//println(clz.supertypes) kotlin中所有类继承 Any
//获取类的属性
clz.memberProperties.forEach { println(it) }//获取自己和父类的所有属性
clz.declaredMemberProperties.forEach { println(it) }//获取自己的属性
clz.primaryConstructor.also { println(it) }//获取主构造函数
clz.constructors.also { println(it) }//获取所有的构造函数
clz.memberFunctions.forEach { println(it) }//获取自己和父类的所有方法(有Any里面的)
clz.declaredMemberFunctions.forEach { println(it) }//获取自己声明的方法(没有Any里面的)
clz.functions.forEach { println(it) }//自己和父类的所有的,和memberFunctions基本差不多
}
open class Father
class Person:Father(){
var name: String = "小王"
var age = 19
}
二.使用KClass创建对象
import kotlin.reflect.KClass
import kotlin.reflect.full.*
fun main() {
//获取类的对象 KClass
//将Any类型转化为Person类型
//即Person.KClass -> Any -> Person
val xw = createObj(Person::class) as Person
println(xw.name)
}
//创建对象
fun createObj(clz: KClass<out Any>): Any{
//1.使用默认 无参 的构造函数创建
//return clz.createInstance()//即使用它的时候必须提供一个无参的构造函数
//2.使用有参数的构造函数创建
val priConstr = clz.primaryConstructor
return priConstr!!.call("老王")
}
open class Father
class Person(var name: String = "小王"):Father(){
var age = 19
constructor():this("小王"){
}
}
三.利用反射调用方法
import kotlin.reflect.KClass
import kotlin.reflect.full.*
fun main() {
invokeFun(Person::class,"show")//my name is 小王 des:老王
}
//调用函数
fun invokeFun(clz: KClass<out Any>,funName: String){
//一般地,我们调用函数时,都是这样: Person().show("ssss"),即先创建对象,然后通过对象调用函数
//首先,获取默认的主构造函数
val priCons = clz.primaryConstructor
//创建对象
val obj = priCons?.call("小王")
//然后,查找你要调用的这个函数是否存在
for(func in clz.functions){
if(func.name == funName){
//当调用类里面的方法时,必须将对象传递过去
//默认第一个参数就是函数的对象
//获取参数的个数
func.parameters.forEach{
//print("第${it.index},个参数")
//print("参数类型为: ${it.type}")
}
func.call(obj,"老王")
break
}
}
}
open class Father
class Person(var name: String = "小王"):Father(){
var age = 19
constructor():this("小王"){
}
fun show(des: String){
println("my name is $name des:$des")
}
}
四.利用反射调用属性
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.*
fun main() {
invokeProperty(Person::class,"age")
}
//访问属性
fun invokeProperty(clz:KClass<out Any>,propName: String){
//平时访问属性就是 Person().name这种
//首先,创建对象
val primary = clz.primaryConstructor
val obj = primary?.call("Android")
//然后,查找age属性
clz.memberProperties.find { it.name == propName }.also {
//调用对象的get方法
val value = it?.call(obj)
//println("获取属性${propName}的值: $value")//获取属性age的值: 19
//调用对象的set方法
//将KProperty类型转化为KMutableProperty类型
//如果属性的修饰符为private,则需要设置isAccessible为true
if(it != null) {
val mpro = it as KMutableProperty1<Any, Any>
mpro.set(obj!!, 18)
val result = it.call(obj)
println(result)//输出了 18
}
}
}
open class Father
class Person(var name: String = "小王"):Father(){
var age = 19
constructor():this("小王"){
}
fun show(des: String){
println("my name is $name des:$des")
}
}
五.反射顶层方法
import kotlin.reflect.KClass
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.*
fun test(){
println("测试")
}
fun main() {
val func = ::test
func.call()//输出 测试
}