当前位置: 首页 > 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/…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...