当前位置: 首页 > news >正文

【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 反射优缺点

  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.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 反射简介 反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff0c;对于任意一个对象&#xff0c;都能够调用它的任意一个方法和属性。 1.1 Kotlin反射 我们对比Kotlin和Java的反射类图。 1.1.1 Kotlin反射常用的数据结…...

基于FPGA的电风扇控制器verilog,视频/代码

名称&#xff1a;基于FPGA的电风扇控制器verilog 软件&#xff1a;QuartusII 语言&#xff1a;Verilog 代码功能&#xff1a; 基于FPGA的电风扇控制器 运用 EDA SOPO实验开发系统设计一个基于FPGA的电风扇定时开关控制器,能实现手动和自动模式之间的切换。要求: (1)KI为电…...

【MySQL】区分:等值连接/自连接/自然连接/外连接 以及ON和Where使用

区分&#xff1a;等值连接/自连接/自然连接/外连接 以及ON和Where使用 一、等值连接二、自连接三、自然连接四、外连接1.左外连接2.右外连接3.全外连接 五、using 和 on六、JOIN 关联表中 ON、WHERE 后面跟条件的区别 一、等值连接 等值连接&#xff1a;它是基于两个表之间的相…...

Windows环境下Apache安装部署说明及常见问题解决

一、软件准备 1.1 Python的下载与安装 见博客 链接: Python下载安装 1.2 Pycharm的下载与安装 见博客 链接: pycharm安装 1.3 Mysql的下载与安装 见博客 链接: MySQL安装 1.4 Navicat的下载与安装 可参考软件安装管家。 解释说明:Pycharm是Python的集成编译环境&#xff0c;Nav…...

Linux-安装docker-compose

前言&#xff1a;本文建立在服务器中已经存在docker环境的基础上&#xff0c;总结了安装docker-compose过程&#xff0c;以及安装过程中遇到的问题和解决方案。 一、下载docker-compose 在网上找了两种&#xff0c;一种是github官方的&#xff0c;一种是国内的镜像 gitbub官…...

机器学习实验一:KNN算法,手写数字数据集(使用汉明距离)

KNN-手写数字数据集: 使用sklearn中的KNN算法工具包( KNeighborsClassifier)替换实现分类器的构建,注意使用的是汉明距离; 分段解释代码: import os import pandas as pd from Levenshtein import hamming导入所需的库,包括os用于文件操作,pandas用于数据处理,以及hamm…...

Java零基础入门-赋值运算符

前言 Java是一门广泛被应用的编程语言&#xff0c;它被用于开发各种类型的应用程序&#xff0c;从桌面应用程序到企业级后端系统。对于零基础的人来说&#xff0c;学习Java可能会感到有些困难。本文将帮助那些没有编程经验的人了解Java的赋值运算符。 摘要 本文将介绍Java中…...

xshell+xming显示jmeter的gui页面

1.下载和安装xming&#xff0c;下载地址&#xff1a;https://sourceforge.net/projects/xming/ 2.配置xming 记住这个端口&#xff0c;一会要用到 修改进入xming安装目录修改host文件 此处是远程服务器的ip 3.服务器执行vi /etc/ssh/sshd_config&#xff0c;修改成如图所示…...

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,您需要知道的预防和恢复方法。

导言&#xff1a; 恶意软件的威胁不断进化&#xff0c;其中之一是.malloxx勒索病毒。这种病毒可以加密您的文件&#xff0c;并要求您支付赎金以解锁它们。本文91数据恢复将详细介绍.malloxx勒索病毒&#xff0c;包括如何恢复被加密的数据文件以及如何预防这种威胁。如果受感染…...

linux中断下文之tasklet(中断二)

在申请 GPIO 中断时使用 request_irq,但是request_irq绑定的中断服务程序指的是中断上文。在 Linux 内核中&#xff0c;tasklet 是一种特殊的软中断机制&#xff0c;被广泛用于处理中断下文相关的任务。它是一种常见且有效的方法&#xff0c;在多核处理系统上可以避免并发问题。…...

Mysql事务+redo日志+锁分类+隔离级别+mvcc

事务&#xff1a; 是数据库操作的最小工作单元&#xff0c;是作为单个逻辑工作单元执行的一系列操作&#xff1b;这些操作作为一个整体一起向系统提交&#xff0c;要么都执行、要么都不执行&#xff1b;事务是一组不可再分割的操作集合&#xff08;工作逻辑单元&#xff09;&a…...

Kafka-Java四:Spring配置Kafka消费者提交Offset的策略

一、Kafka消费者提交Offset的策略 Kafka消费者提交Offset的策略有 自动提交Offset&#xff1a; 消费者将消息拉取下来以后未被消费者消费前&#xff0c;直接自动提交offset。自动提交可能丢失数据&#xff0c;比如消息在被消费者消费前已经提交了offset&#xff0c;有可能消息…...

Python 训练集、测试集以及验证集切分方法:sklearn及手动切分

目录 方法一 方法二 需求目的&#xff1a;针对模型训练输入&#xff0c;按照6:2:2的比例进行训练集、测试集和验证集的划分。当前数据量约10万条。如果针对的是记录条数达上百万的数据集&#xff0c;可按照98:1:1的比例进行切分。 方法一&#xff1a;切分训练集和测试集&…...

数据结构,及分类(存储分类、逻辑分类)介绍

一、数据结构&#xff1a; 数据是软件开发的核心。在软件开发过程中基本上就是对数据的新增、删除、修改、查看的操作。 如何合理存储数据&#xff0c;如何有效提升数据操作开发效率&#xff0c;都是软件开发中的重中之重。使用合理的数据结构是非常重要的。 1.1简介&#xff…...

Powershell脚本自动备份dhcp数据库

文章目录 为什么要备份DHCP数据库呢&#xff1f;在PowerShell中自动备份DHCP数据库1&#xff0c;创建备份目录2&#xff0c;判断备份路径是否存在3&#xff0c;备份DHCP数据库4&#xff0c;完整自动备份脚本5&#xff0c;安排定期备份 推荐阅读 为什么要备份DHCP数据库呢&#…...

第十六章总结:反射和注解

.1.1&#xff1a;访问构造方法 反射&#xff1a; 1.class类 2.获取构造方法 3.获取成员属性 4.获取成员方法 注解 1.内置注解 2.反射注解 3 创建Class对象的三种方式 1.使用getClass&#xff08;&#xff09;方法 object str new object&#xff08;&#xff09;…...

mysql 切割字符串函数

93、mysql 切割字符串函数 需求&#xff0c;使用in 匹配多个参数&#xff0c;name字段值类型&#xff1a;1234(小明) 结果&#xff1a; select * from user where SUBSTRING_INDEX(REPLACE(name, ), ), (, -1) in ( 小明,小李)使用的函数如下 1、使用SUBSTRING_INDEX函数 SU…...

汽车发动机电机右盖设计

摘要 随着我国微型电子技术和社会经济的发展&#xff0c;目前行业内为满足客户需求出现了大量的电器设备&#xff0c;而大多数的电气设备的重要组成中都有电机&#xff0c;并且电机端盖成为电机研发人员重点关注和研究的对象&#xff0c;逐渐成为电机的重要组成部分&#xff0c…...

ETHERNET/IP从站转CANOPEN主站连接AB系统的配置方法

你还在为配置网关的ETHERNET/IP从站和CANOPEN主站发愁吗&#xff1f;今天来教你解决办法&#xff01; 一&#xff0c;首先&#xff0c;配置网关的ETHERNET/IP从站&#xff0c;需要使用AB系统的配置方法&#xff0c;具体步骤如下 1&#xff0c;使用 AB 系统配置网关的 ETHERNET/…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了&#xff0c;很多小伙伴想体验鸿蒙电脑版操作系统&#xff0c;可惜&#xff0c;鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机&#xff0c;来体验大家心心念念的鸿蒙系统啦&#xff01;注意&#xff1a;虚拟…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...

未授权访问事件频发,我们应当如何应对?

在当下&#xff0c;数据已成为企业和组织的核心资产&#xff0c;是推动业务发展、决策制定以及创新的关键驱动力。然而&#xff0c;未授权访问这一隐匿的安全威胁&#xff0c;正如同高悬的达摩克利斯之剑&#xff0c;时刻威胁着数据的安全&#xff0c;一旦触发&#xff0c;便可…...

Linux入门(十五)安装java安装tomcat安装dotnet安装mysql

安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了&#xff0c;系统很多命…...