【Kotlin精简】第6章 反射

这篇具有很好参考价值的文章主要介绍了【Kotlin精简】第6章 反射。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 反射简介

反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性。

1.1 Kotlin反射

【Kotlin精简】第6章 反射,Kotlin,Android,1024程序员节,kotlin,android,反射
【Kotlin精简】第6章 反射,Kotlin,Android,1024程序员节,kotlin,android,反射
我们对比Kotlin和Java的反射类图。

1.1.1 Kotlin反射常用的数据结构

数据结构 概念及使用说明
KType 描述未擦除的类型或泛型参数等,例如 Map<String,Int>;可通过 typeof 或者以下类型获取对应的父类、属性、函数参数等
KClass 描述对象的实际类型,不包含泛型参数,例如Map可通过对象、类型名直接获得
KProperty 描述属性,可通过属性引用、属性所在类的 KClass 获取
KFunction 描述函数,可通过函数引用、函数所在类的 KClass 获取

1.2 对比Java反射

【Kotlin精简】第6章 反射,Kotlin,Android,1024程序员节,kotlin,android,反射
【Kotlin精简】第6章 反射,Kotlin,Android,1024程序员节,kotlin,android,反射

1.2.1 Kotlin与Java 反射优缺点

  1. Java 反射
    优点:无需引入额外依赖,首次使用速度相对较快
    缺点: 无法访问 Kotlin 语法特性,需对 Kotlin 生成的字节码足够了解

  2. Kotlin 反射
    优点: 支持访问 Kotlin 几乎所有特性,API 设计更友好
    缺点:引入 Kotin 反射库(2.5MB,编译后 400KB),首次调用慢

1.3 反射用途

  1. 在运行时判断任意一个**对象所属的类**
  2. 在运行时构造任意一个**类的对象**
  3. 在运行时判断任意一个**类所具有的成员变量和方法**
  4. 在运行时调用任意一个**对象的方法**

2 Kotlin反射

2.1 反射使用

Kotlin 的反射需要集成 org.jetbrains.kotlin:kotlin-reflect 仓库,版本保持与 Kotlin 一致。

implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

Kotlin中,字节码对应的类是kotlin.reflect.KClass,因为Kotlin百分之百兼容Java,所以Kotlin中可以使用Java中的反射,但是由于Kotlin中字节码.class对应的是KClass类,所以如果想要使用Java中的反射,需要首先获取Class的实例,在Kotlin中可以通过以下两种方式来获取Class实例。

//1.通过实例.javaClass
var hello = HelloWorld()
hello.javaClass

 //2.通过类Kclass类的.java属性
HelloWorld::class.java

获取了Class实例,就可以调用上面介绍的方法,获取各种在Java中定义的类的信息了。

当然Kotlin中除了可以使用Java中的反射以外,还可以使用Kotlin中声明的一些方法,当然同Java中反射一样,想要使用这些方法,先要获取Kclass对象,在Kotlin中可以通过以下两种方式获取KClass实例。

 //1.通过类::class的方式获取Kclass实例
val clazz1: KClass<*> = HelloWorld::class
//2.通过实例.javaClass.kotlin获取Kclass实例
var hello = HelloWorld()
val clazz2 = hello.javaClass.kotlin

2.2 常用API

2.2.1 构造函数Constructor

//返回这个类的所有构造器
public val constructors: Collection<KFunction<T>>

2.2.2 成员变量和成员函数

 //返回类可访问的所有函数和属性,包括继承自基类的,但是不包括构造器
 override val members: Collection<KCallable<*>>
 //返回类声明的所有函数
 val KClass<*>.declaredFunctions: Collection<KFunction<*>>
 //返回类的扩展函数
 val KClass<*>.declaredMemberExtensionFunctions: Collection<KFunction<*>>
 //返回类的扩展属性
 val <T : Any> KClass<T>.declaredMemberExtensionProperties: Collection<KProperty2<T, *, *>>
 //返回类自身声明的成员函数
 val KClass<*>.declaredMemberFunctions: Collection<KFunction<*>>
 //返回类自身声明的成员变量(属性)
 val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>>

2.2.3 类相关信息

//1.返回类的名字
public val simpleName: String?
//2.返回类的全包名
public val qualifiedName: String?
//3.如果这个类声明为object,则返回其实例,否则返回null
public val objectInstance: T?
//4.返回类的可见性
@SinceKotlin("1.1")
public val visibility: KVisibility?
//5.判断类是否为final类(在Kotlin中,类默认是final的,除非这个类声明为open或者abstract)
@SinceKotlin("1.1")
public val isFinal: Boolean
//6.判断类是否是open的(abstract类也是open的),表示这个类可以被继承
@SinceKotlin("1.1")
public val isOpen: Boolean
//7.判断类是否为抽象类
@SinceKotlin("1.1")
public val isAbstract: Boolean
//8.判断类是否为密封类,密封类:用sealed修饰,其子类只能在其内部定义
@SinceKotlin("1.1")
public val isSealed: Boolean
//9.判断类是否为data类
@SinceKotlin("1.1")
public val isData: Boolean
//10.判断类是否为成员类
@SinceKotlin("1.1")
public val isInner: Boolean
//11.判断类是否为companion object
@SinceKotlin("1.1")
public val isCompanion: Boolean 
//12.返回类中定义的其他类,包括内部类(inner class声明的)和嵌套类(class声明的)
public val nestedClasses: Collection<KClass<*>>
 //13.判断一个对象是否为此类的实例
@SinceKotlin("1.1")
public fun isInstance(value: Any?): Boolean
//14.返回这个类的泛型列表
@SinceKotlin("1.1")
public val typeParameters: List<KTypeParameter>
//15.类其直接基类的列表
@SinceKotlin("1.1")
public val supertypes: List<KType>
//16.返回类所有的基类
val KClass<*>.allSuperclasses: Collection<KClass<*>>
//17.返回类的伴生对象companionObject
val KClass<*>.companionObject: KClass<*>?

2.3 使用demo

package com.yvan.demo.reflect

import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.*
import kotlin.reflect.jvm.isAccessible

//定义注解
annotation class Anno

@Deprecated("该类已经不推荐使用")
@Anno
class ReflectA(val name: String) {

    companion object{
        const val TAG = "ReflectA"
        fun show(){

        }
    }

    var age: Int = 0

    constructor() : this("ReflectA_")

    constructor(name: String, age: Int) : this(name) {
        this.age = age
    }

    fun print(str: String) {
        println("ReflectA print str $str")
    }

    fun sayHi(): String {
        println("ReflectA sayHi")
        return "sayHi"
    }

    class InnerClass
}

// 拓展方法
fun ReflectA.exfun() {
    println("exfun")
}

// 拓展属性
val ReflectA.foo: Double
    get() = 3.14


fun main() {
    println("Hello word")

    val clazz = ReflectA::class
    println(clazz)

    println("ReflectA 的全部构造器如下:")
    clazz.constructors.forEach {
        println(it)
    }

    println("ReflectA 的主构造器如下:")
    println(clazz.primaryConstructor)

    println(" ")
    //通过functions属性获取该KClass对象所对应类的全部方法
    val funs = clazz.functions
    println("ReflectA 的全部方法如下:")
    funs.forEach { println(it) }

    println(" ")
    //通过 declaredFunctions 属性获取该KClass对象声明的全部方法
    val funs2 = clazz.declaredFunctions
    println("ReflectA 本身声明的全部方法如下:")
    funs2.forEach { println(it) }

    println(" ")
    //通过 memberExtensionFunctions 属性获取全部扩展方法
    val exetensionFunctions = clazz.memberExtensionFunctions
    println("ReflectA 声明的扩展方法如下:")
    exetensionFunctions.forEach { println(it) }

    println(" ")
    //通过decaredMemberProperties获取全部成员属性
    var memberProperties = clazz.declaredMemberProperties
    println("ReflectA 本身声明的成员属性如下:")
    memberProperties.forEach { println(it) }

    println(" ")
    //通过memberExtensionProperties属性获取该KClass对象的全部扩展属性
    var exProperties = clazz.memberExtensionProperties
    println("ReflectA 本身声明的扩展属性如下:")
    exProperties.forEach { println(it) }

    println(" ")
    //通过annotations属性获取该KClass对象所对应类的全部注解
    val anns = clazz.annotations
    println("ReflectA 的全部注解如下:")
    anns.forEach { println(it) }
    println("该KClass元素上的@Annot注解为:${clazz.findAnnotation<Anno>()}")

    println(" ")
    //通过nestedClasses属性获取所对应的全部嵌套类
    val inners = clazz.nestedClasses
    println("ReflectA 的全部内部类如下:")
    inners.forEach { println(it) }

    println(" ")
    //通过supertypes属性获取该类的所有父类型
    println("KClassTest的父类型为:${clazz.supertypes}")


    println(" ")
    println("---------- companion 对象 ---------") //
    val companion = clazz.companionObject // 返回也是一个 KClass
    if (companion != null){
        println("companion $companion")
        companion.declaredMemberProperties.forEach {
            println("companion declaredMemberProperties:  $it")
        }
        companion.declaredFunctions.forEach {
            println("companion declaredFunctions:  $it")
        }
    }


    println(" ")


    println("---------- 创建对象 ---------")
    println(" ")
    println("createInstance 创建实例")
    // createInstance() 方法调用无参数的构造器创建实例
    val inst2 = clazz.createInstance()
    println(inst2.name)
    println(inst2.age)

    println(" ")
    // primaryConstructor 主构造函数
    val cons1 = clazz.primaryConstructor
    val inst1 = cons1?.call("hello reflect")  // 参入参数
    println(inst1)
    println("inst1 " + inst1?.name)

    println(" ")
    println("第一个构造函数")
    val cons2 = clazz.constructors.first()
    println(cons2)

    println(" ")

    println("-------调用方法------")
    val funs3 = clazz.declaredFunctions
    val inst3 = clazz.createInstance()
    println("ReflectA 本身声明的全部方法如下:")
    funs3.forEach { println(it) }
    for (f in funs3) {
        if (f.name == "sayHi") {
            f.call(inst3)
        }
        if (f.name == "print") {
            f.call(inst3, "反射打印")
        }
    }

    println("\n")
    println("-------访问属性------")
    //通过decaredMemberProperties获取全部成员属性
    val memberProperties2 = clazz.declaredMemberProperties
    val inst4 = clazz.createInstance()
    println("ReflectA 本身声明的成员属性如下:")
    memberProperties2.forEach { println(it) }
    println("inst4 name: ${inst4.name}")
    memberProperties2.forEach {
        if (it.name == "age") {
            it as KMutableProperty1<ReflectA, Int>
            it.isAccessible = true
            it.set(inst4, 20)
            println(it.get(inst4))
        }

    }
}

3 Kotlin反射总结

反射是一种在运行时动态访问对象属性和方法的方式,而不需事先确定这些属性是什么。
一般来说当你访问一个对象的方法或者属性时,程序的源代码会因用一个具体的声明,编译器将静态解析这个引用并确保这个声明是存在的。但有时候你要编写能够使用任意类型的对象的代码,或者只能在运行时才能确定要访问的方法和属性的名称。文章来源地址https://www.toymoban.com/news/detail-716767.html

到了这里,关于【Kotlin精简】第6章 反射的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 好用且免费的CodeWhisperer,给1024程序员节送礼来了

          国庆期间没有胆量去人从众的景点,关在家里刷手机时意外在亚马逊的User Group公众号上发现了CodeWhisperer这么个好东西(bu yao qian),以后撸代码也可以提高生产力(fang yang mo yu)了,这还不赶紧上手试一下。看官方介绍说它支持流行的IDE开发工具,包括VS Code、Intelli

    2024年02月08日
    浏览(47)
  • 1024程序员节带你玩转图片Exif信息获取之JavaScript

    目录 一、前言 二、背景 三、Exif.js          1、Exif.js 简介 2、Exif.js 引入 四、多场景展示数据获取 1、原始图片直接获取  2、base64 编码文件加载  3、文件上传的方式加载  五、总结        1024是2的十次方,二进制计数的基本计量单位之一。1G=1024M,而1G与1级谐音,也有一

    2024年02月20日
    浏览(56)
  • 1024程序员节特辑 | Spring Boot实战 之 MongoDB分片或复制集操作

    Spring实战系列文章: Spring实战 | Spring AOP核心秘笈之葵花宝典 Spring实战 | Spring IOC不能说的秘密? 国庆中秋特辑系列文章: 国庆中秋特辑(八)Spring Boot项目如何使用JPA 国庆中秋特辑(七)Java软件工程师常见20道编程面试题 国庆中秋特辑(六)大学生常见30道宝藏编程面试题

    2024年02月08日
    浏览(76)
  • 1024程序员节特辑 | ELK+ 用户画像构建个性化推荐引擎,智能实现“千人千面”

    专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271502.html tensorflow专栏:https://blog.csdn.net/superdangbo/category_869

    2024年02月07日
    浏览(80)
  • 1024程序员狂欢节 | IT前沿技术、人工智能、数据挖掘、网络空间安全技术

    一年一度的1024程序员狂欢节又到啦!成为更卓越的自己,坚持阅读和学习,别给自己留遗憾,行动起来吧! 那么,都有哪些好书值得入手呢?小编为大家整理了前沿技术、人工智能、集成电路科学与芯片技术、新一代信息与通信技术、网络空间安全技术,四大热点领域近期

    2024年02月06日
    浏览(64)
  • 1024程序员节特辑 | 解密Spring Cloud Hystrix熔断提高系统的可用性和容错能力

    专栏集锦,大佬们可以收藏以备不时之需 Spring Cloud实战专栏:https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏:https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏:https://blog.csdn.net/superdangbo/category_9271502.html tensorflow专栏:https://blog.csdn.net/superdangbo/category_869

    2024年02月08日
    浏览(50)
  • 1024程序员节?我们整点AI绘图玩玩吧,一文教你配置stable-diffusion

    需提前准备:一台高性能的电脑(尤其是显存)、python、Git、梯子。 其实Github上有很多关于Stable diffusion的库,综合对比之后,我选取的是比较全面的AUTOMATIC1111这个,源码链接:Stable-diffusion(Github) 找到安装那块的教程,此教程以windows为例。 ps:如果你电脑上已经有了pyt

    2024年01月16日
    浏览(71)
  • PHP框架开发实践 | 1024 程序员节:通过index.php找到对应的controller是如何实现的

    🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于PHP专栏:PHP进阶实战教程。 🎉欢迎 👍点赞✍评论⭐收藏

    2024年02月08日
    浏览(67)
  • 【Kotlin精简】第7章 泛型

    泛型 即 “ 参数化类型 ”,将类型参数化,可以用在 类 , 接口 , 函数 上。与 Java 一样, Kotlin 也提供 泛型 ,为 类型安全 提供保证, 消除类型强转 的烦恼。 类型安全 :通用允许仅保留单一类型的对象。泛型不允许存储其他对象。 不需要类型转换 :不需要对对象进行类

    2024年02月05日
    浏览(38)
  • 1024程序员狂欢节有好礼 | 前沿技术、人工智能、集成电路科学与芯片技术、新一代信息与通信技术、网络空间安全技术

    🌹欢迎来到 爱书不爱输的程序猿 的博客, 本博客致力于知识分享,与更多的人进行学习交流 🚩🚩🚩 点击直达福利 一年一度的1024程序员狂欢节又到啦!成为更卓越的自己,坚持阅读和学习,别给自己留遗憾,行动起来吧! 那么,都有哪些好书值得入手呢?小编为大家整理

    2024年02月08日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包