【Kotlin精简】第6章 反射
1 反射简介
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性。
1.1 Kotlin反射


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


1.2.1 Kotlin与Java 反射优缺点
-
Java 反射
优点:无需引入额外依赖,首次使用速度相对较快
缺点: 无法访问 Kotlin 语法特性,需对 Kotlin 生成的字节码足够了解 -
Kotlin 反射
优点: 支持访问 Kotlin 几乎所有特性,API 设计更友好
缺点:引入 Kotin 反射库(2.5MB,编译后 400KB),首次调用慢
1.3 反射用途
- 在运行时判断任意一个**
对象所属的类** - 在运行时构造任意一个**
类的对象** - 在运行时判断任意一个**
类所具有的成员变量和方法** - 在运行时调用任意一个**
对象的方法**
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.reflectimport 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 = 0constructor() : 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: Doubleget() = 3.14fun main() {println("Hello word")val clazz = ReflectA::classprintln(clazz)println("ReflectA 的全部构造器如下:")clazz.constructors.forEach {println(it)}println("ReflectA 的主构造器如下:")println(clazz.primaryConstructor)println(" ")//通过functions属性获取该KClass对象所对应类的全部方法val funs = clazz.functionsprintln("ReflectA 的全部方法如下:")funs.forEach { println(it) }println(" ")//通过 declaredFunctions 属性获取该KClass对象声明的全部方法val funs2 = clazz.declaredFunctionsprintln("ReflectA 本身声明的全部方法如下:")funs2.forEach { println(it) }println(" ")//通过 memberExtensionFunctions 属性获取全部扩展方法val exetensionFunctions = clazz.memberExtensionFunctionsprintln("ReflectA 声明的扩展方法如下:")exetensionFunctions.forEach { println(it) }println(" ")//通过decaredMemberProperties获取全部成员属性var memberProperties = clazz.declaredMemberPropertiesprintln("ReflectA 本身声明的成员属性如下:")memberProperties.forEach { println(it) }println(" ")//通过memberExtensionProperties属性获取该KClass对象的全部扩展属性var exProperties = clazz.memberExtensionPropertiesprintln("ReflectA 本身声明的扩展属性如下:")exProperties.forEach { println(it) }println(" ")//通过annotations属性获取该KClass对象所对应类的全部注解val anns = clazz.annotationsprintln("ReflectA 的全部注解如下:")anns.forEach { println(it) }println("该KClass元素上的@Annot注解为:${clazz.findAnnotation<Anno>()}")println(" ")//通过nestedClasses属性获取所对应的全部嵌套类val inners = clazz.nestedClassesprintln("ReflectA 的全部内部类如下:")inners.forEach { println(it) }println(" ")//通过supertypes属性获取该类的所有父类型println("KClassTest的父类型为:${clazz.supertypes}")println(" ")println("---------- companion 对象 ---------") //val companion = clazz.companionObject // 返回也是一个 KClassif (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.primaryConstructorval 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.declaredFunctionsval 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.declaredMemberPropertiesval 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 = trueit.set(inst4, 20)println(it.get(inst4))}}
}
3 Kotlin反射总结
反射是一种在运行时动态访问对象属性和方法的方式,而不需事先确定这些属性是什么。
一般来说当你访问一个对象的方法或者属性时,程序的源代码会因用一个具体的声明,编译器将静态解析这个引用并确保这个声明是存在的。但有时候你要编写能够使用任意类型的对象的代码,或者只能在运行时才能确定要访问的方法和属性的名称。
相关文章:
【Kotlin精简】第6章 反射
1 反射简介 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性。 1.1 Kotlin反射 我们对比Kotlin和Java的反射类图。 1.1.1 Kotlin反射常用的数据结…...
基于FPGA的电风扇控制器verilog,视频/代码
名称:基于FPGA的电风扇控制器verilog 软件:QuartusII 语言:Verilog 代码功能: 基于FPGA的电风扇控制器 运用 EDA SOPO实验开发系统设计一个基于FPGA的电风扇定时开关控制器,能实现手动和自动模式之间的切换。要求: (1)KI为电…...
【MySQL】区分:等值连接/自连接/自然连接/外连接 以及ON和Where使用
区分:等值连接/自连接/自然连接/外连接 以及ON和Where使用 一、等值连接二、自连接三、自然连接四、外连接1.左外连接2.右外连接3.全外连接 五、using 和 on六、JOIN 关联表中 ON、WHERE 后面跟条件的区别 一、等值连接 等值连接:它是基于两个表之间的相…...
Windows环境下Apache安装部署说明及常见问题解决
一、软件准备 1.1 Python的下载与安装 见博客 链接: Python下载安装 1.2 Pycharm的下载与安装 见博客 链接: pycharm安装 1.3 Mysql的下载与安装 见博客 链接: MySQL安装 1.4 Navicat的下载与安装 可参考软件安装管家。 解释说明:Pycharm是Python的集成编译环境,Nav…...
Linux-安装docker-compose
前言:本文建立在服务器中已经存在docker环境的基础上,总结了安装docker-compose过程,以及安装过程中遇到的问题和解决方案。 一、下载docker-compose 在网上找了两种,一种是github官方的,一种是国内的镜像 gitbub官…...
机器学习实验一:KNN算法,手写数字数据集(使用汉明距离)
KNN-手写数字数据集: 使用sklearn中的KNN算法工具包( KNeighborsClassifier)替换实现分类器的构建,注意使用的是汉明距离; 分段解释代码: import os import pandas as pd from Levenshtein import hamming导入所需的库,包括os用于文件操作,pandas用于数据处理,以及hamm…...
Java零基础入门-赋值运算符
前言 Java是一门广泛被应用的编程语言,它被用于开发各种类型的应用程序,从桌面应用程序到企业级后端系统。对于零基础的人来说,学习Java可能会感到有些困难。本文将帮助那些没有编程经验的人了解Java的赋值运算符。 摘要 本文将介绍Java中…...
xshell+xming显示jmeter的gui页面
1.下载和安装xming,下载地址:https://sourceforge.net/projects/xming/ 2.配置xming 记住这个端口,一会要用到 修改进入xming安装目录修改host文件 此处是远程服务器的ip 3.服务器执行vi /etc/ssh/sshd_config,修改成如图所示…...
el-tree业务
<el-form-item label"选择节点" prop"node_ids"><el-checkboxv-if"regionList.length"v-model"selectAll":disabled"selectDisabled":indeterminate"isIndeterminate":show-checkbox"!selectDisabl…...
警惕Mallox勒索病毒的最新变种malloxx,您需要知道的预防和恢复方法。
导言: 恶意软件的威胁不断进化,其中之一是.malloxx勒索病毒。这种病毒可以加密您的文件,并要求您支付赎金以解锁它们。本文91数据恢复将详细介绍.malloxx勒索病毒,包括如何恢复被加密的数据文件以及如何预防这种威胁。如果受感染…...
linux中断下文之tasklet(中断二)
在申请 GPIO 中断时使用 request_irq,但是request_irq绑定的中断服务程序指的是中断上文。在 Linux 内核中,tasklet 是一种特殊的软中断机制,被广泛用于处理中断下文相关的任务。它是一种常见且有效的方法,在多核处理系统上可以避免并发问题。…...
Mysql事务+redo日志+锁分类+隔离级别+mvcc
事务: 是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元)&a…...
Kafka-Java四:Spring配置Kafka消费者提交Offset的策略
一、Kafka消费者提交Offset的策略 Kafka消费者提交Offset的策略有 自动提交Offset: 消费者将消息拉取下来以后未被消费者消费前,直接自动提交offset。自动提交可能丢失数据,比如消息在被消费者消费前已经提交了offset,有可能消息…...
Python 训练集、测试集以及验证集切分方法:sklearn及手动切分
目录 方法一 方法二 需求目的:针对模型训练输入,按照6:2:2的比例进行训练集、测试集和验证集的划分。当前数据量约10万条。如果针对的是记录条数达上百万的数据集,可按照98:1:1的比例进行切分。 方法一:切分训练集和测试集&…...
数据结构,及分类(存储分类、逻辑分类)介绍
一、数据结构: 数据是软件开发的核心。在软件开发过程中基本上就是对数据的新增、删除、修改、查看的操作。 如何合理存储数据,如何有效提升数据操作开发效率,都是软件开发中的重中之重。使用合理的数据结构是非常重要的。 1.1简介ÿ…...
Powershell脚本自动备份dhcp数据库
文章目录 为什么要备份DHCP数据库呢?在PowerShell中自动备份DHCP数据库1,创建备份目录2,判断备份路径是否存在3,备份DHCP数据库4,完整自动备份脚本5,安排定期备份 推荐阅读 为什么要备份DHCP数据库呢&#…...
第十六章总结:反射和注解
.1.1:访问构造方法 反射: 1.class类 2.获取构造方法 3.获取成员属性 4.获取成员方法 注解 1.内置注解 2.反射注解 3 创建Class对象的三种方式 1.使用getClass()方法 object str new object()…...
mysql 切割字符串函数
93、mysql 切割字符串函数 需求,使用in 匹配多个参数,name字段值类型:1234(小明) 结果: select * from user where SUBSTRING_INDEX(REPLACE(name, ), ), (, -1) in ( 小明,小李)使用的函数如下 1、使用SUBSTRING_INDEX函数 SU…...
汽车发动机电机右盖设计
摘要 随着我国微型电子技术和社会经济的发展,目前行业内为满足客户需求出现了大量的电器设备,而大多数的电气设备的重要组成中都有电机,并且电机端盖成为电机研发人员重点关注和研究的对象,逐渐成为电机的重要组成部分,…...
ETHERNET/IP从站转CANOPEN主站连接AB系统的配置方法
你还在为配置网关的ETHERNET/IP从站和CANOPEN主站发愁吗?今天来教你解决办法! 一,首先,配置网关的ETHERNET/IP从站,需要使用AB系统的配置方法,具体步骤如下 1,使用 AB 系统配置网关的 ETHERNET/…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
