【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/…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...