Kotlin 中的 `reified` 关键字全解析:保留类型信息 + 优化高阶函数的双重魔法
在使用 Kotlin 编写泛型函数时,你是否遇到过这样的尴尬:你想判断某个对象是不是泛型类型 T,结果却发现代码根本编译不过?这是因为 Kotlin 和 Java 一样,泛型在运行时会被类型擦除。
为了解决这个问题,Kotlin 提供了一个非常有用的关键字:reified。本篇博客将通过简单的例子带你了解:
- 为什么需要
reified - 如何使用
inline + reified来保留类型信息 inline本身的另一个用处:优化高阶函数性能- 两种方式的对比及适用场景
🎯 为什么需要 reified
来看一个经典的错误示例:
fun <T> isOfType(value: Any): Boolean {return value is T // ❌ 编译失败:Cannot check for instance of erased type
}
这是因为 T 是泛型参数,在运行时类型信息已经被擦除了,所以无法直接用 is T 来判断类型。
✅ 使用 inline + reified 的正确写法
在 Kotlin 中,我们可以通过将函数标记为 inline,并使用 reified 保留泛型类型,从而解决这个问题。
inline fun <reified T> isOfType(value: Any): Boolean {return value is T
}
使用方式:
fun main() {println(isOfType<String>("Hello")) // trueprintln(isOfType<Int>("Hello")) // false
}
reified的字面意思是“具体化的”,即让类型参数在运行时仍然是“具体的”而非被擦除。
🧠 reified 的另一个作用:配合高阶函数使用
我们知道 inline 最初的设计是为了优化高阶函数(即 lambda 表达式)的性能。但当你结合 reified 使用时,inline 函数就解锁了新能力。
来看这个例子:我们希望传入一个对象和一段逻辑,只有当对象类型匹配时才执行逻辑。
inline fun <reified T> doIfMatch(value: Any, action: (T) -> Unit) {if (value is T) {action(value)} else {println("类型不匹配,不执行")}
}
调用方式:
fun main() {val anyValue: Any = "Hello Kotlin"doIfMatch<String>(anyValue) {println("字符串长度是:${it.length}")}doIfMatch<Int>(anyValue) {println("这个不会执行")}
}
这个例子就同时体现了 inline 的两个用途:
- 💡 类型具体化:通过
reified实现is T的类型判断 - 🚀 高阶函数优化:避免创建 lambda 对象,提升性能
🤯 如果没有 reified 会怎么样?
不使用 reified 的话,你必须手动传入 Class<T> 类型信息:
fun <T> doIfMatchWithoutReified(value: Any, clazz: Class<T>, action: (T) -> Unit) {if (clazz.isInstance(value)) {@Suppress("UNCHECKED_CAST")action(value as T)} else {println("类型不匹配,不执行")}
}
调用方式:
fun main() {doIfMatchWithoutReified("Hello", String::class.java) {println("执行了:$it")}
}
虽然功能一致,但语法繁琐,也不够 Kotlin 风格。
🔍 总结
| 功能 | inline + reified | 普通泛型 |
|---|---|---|
是否能用 is T | ✅ 是 | ❌ 否 |
是否能获取 T::class | ✅ 是 | ❌ 否 |
是否需要传入 Class<T> | ❌ 不需要 | ✅ 需要 |
| 是否可用在高阶函数中优化性能 | ✅ 是 | ✅ 是(只 inline 部分) |
✅ 使用建议
- 如果你写的是泛型函数并需要类型判断或反射功能,请考虑使用
inline + reified。 - 如果你需要频繁传 lambda,请使用
inline优化性能。 - 记住:
reified只能用于inline函数中,因为类型信息只有在内联时才能保留下来。
相关文章:
Kotlin 中的 `reified` 关键字全解析:保留类型信息 + 优化高阶函数的双重魔法
在使用 Kotlin 编写泛型函数时,你是否遇到过这样的尴尬:你想判断某个对象是不是泛型类型 T,结果却发现代码根本编译不过?这是因为 Kotlin 和 Java 一样,泛型在运行时会被类型擦除。 为了解决这个问题,Kotl…...
在CPU服务器上部署Ollama和Dify的过程记录
在本指南中,我将详细介绍如何在CPU服务器上安装和配置Ollama模型服务和Dify平台,以及如何利用Docker实现这些服务的高效部署和迁移。本文分为三大部分:Ollama部署、Dify环境配置和Docker环境管理,适合需要在本地或私有环境中运行A…...
【计网】TCP 协议详解 与 常见面试题
三次握手、四次挥手的常见面试题 不用死记,只需要清楚三次握手,四次挥手的流程,回答的时候心里要记住,假设网络是不可靠的 问题(1):为什么关闭连接时需要四次挥手,而建立连接却只要三次握手? 关…...
Java 基础-31-枚举-认识枚举
在Java编程语言中,枚举(Enum)是一种特殊的类,它允许一组固定的常量。它们非常适合用来表示一组固定的值,比如星期几、季节、颜色等。枚举自Java 5开始引入,为定义常量提供了一种更强大和方便的方式。本文将…...
7.4 SVD 的几何背景
一、SVD 的几何解释 SVD 将矩阵分解成三个矩阵的乘积: ( 正交矩阵 ) ( 对角矩阵 ) ( 正交矩阵 ) (\pmb{正交矩阵})\times(\pmb{对角矩阵})(\pmb{正交矩阵}) (正交矩阵)(对角矩阵)(正交矩阵),用几何语言表述其几何背景: ( 旋转 ) ( 伸缩 )…...
低延迟云网络的核心技术
低延迟云网络通过架构优化、协议创新、硬件加速等多维度技术手段,将数据传输延迟降低至毫秒级甚至微秒级。 1. 网络架构优化 1.1 扁平化网络Leaf-Spine 架构 减少网络层级,缩短数据转发路径(如数据中心内部一跳可达)。 扁平化网络Leaf-Spine(叶子-脊椎)架构是一种现代…...
C++的多态-上
目录 多态的概念 多态的定义及实现 1.虚函数 2. 多态的实现 2.1.多态构成条件 2.2.虚函数重写的两个例外 (1)协变(基类与派生类虚函数返回值类型不同) (2)析构函数的重写(基类与派生类析构函数的名字不同) 2.3.多态的实现 2.4.多态在析构函数中的应用 2.5.多态构成条…...
内存与显存:从同根生到殊途异路的科技演进
在现代计算机的世界里,内存和显存是两个不可或缺的硬件组件。它们看似功能相近,却在发展历程中逐渐分道扬镳,各自服务于不同的计算需求。今天,我们将从一根内存条和一块显卡入手,深入探讨内存与显存的异同,…...
手搓多模态-04 归一化介绍
在机器学习中,归一化是一个非常重要的工具,它能帮助我们加速训练的速度。在我们前面的SiglipVisionTransformer 中,也有用到归一化层,如下代码所示: class SiglipVisionTransformer(nn.Module): ##视觉模型的第二层&am…...
【C++】第八节—string类(上)——详解+代码示例
hello,又见面了! 云边有个稻草人-CSDN博客 C_云边有个稻草人的博客-CSDN博客——C专栏(质量分高达97!) 菜鸟进化中。。。 目录 一、为什么要学习string类? 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) …...
Java 数组与 ArrayList 核心区别解析:从源码到实战!!!
🌟 Java 数组与 ArrayList 核心区别解析:从源码到实战 💡 Java 开发者必读! 数组(Array)和 ArrayList 是 Java 中最常用的数据存储结构,但它们的底层设计、性能表现和适用场景差异显著。本文通…...
【易飞】易飞批量选择品号处理方法,工作效率提升300%
开窗选择品号方式要么手动输入,要么以什么开头、包含、从A物料到B物料查询后返回的有规律的品号。对于没有规律且大量品号的处理方式是否有便捷的方法呢? 尤其在通常在查询多阶材料清单,查询库存明细表,整批变更元件等如品号无规律情况下,只能一个个选择,无法通过EXCEL方…...
【最新版】啦啦外卖v64系统独立版源码+全部小程序APP端+安装教程
一.系统介绍 啦啦外卖跑腿平台独立版,使用的都知道该系统功能非常强大,应该说是目前外卖平台功能最全的一套系统。主要是功能非常多,拿来即用,包括客户端小程序、配送端小程序、商户端小程序,还有对应四个端的APP源码…...
iproute2 工具集使用详解
目录 一、iproute2 核心命令:ip二、常用功能详解1. 管理网络接口(link 对象)2. 管理 IP 地址(address 对象)3. 管理路由表(route 对象)4. 管理 ARP 和邻居缓存(neigh 对象࿰…...
项目总结之常问的一些问题
1.项目功能介绍,重难点 重难点: mock工具使用(涉及到的三方接口过多,由于网络等原因无法调通,所以测试的时候,采用mock工具来模拟返回接口真正调用后响应数据) 2.项目负责哪部分?…...
C语言查漏补缺:占位符篇
占位符篇 1. 整数类型2. 字符类型3. 浮点数类型4. 指针类型5. 字符串6. 修饰符 1. 整数类型 %d / %i:用于 int(有符号十进制整数)。int num -42; printf("%d", num); // 输出: -42%u:用于 unsigned int(无…...
cut命令用法
cut 是 Linux/Unix 系统中一个用于按列提取文本内容的命令,常用于处理结构化文本(如 CSV、日志、配置文件等)。它通过分隔符、字符位置或字节位置来切割文本,提取指定部分。 核心功能 按字段(列)提取&#…...
java 正则表达式优化
1,什么是正则表达式 正则表达式使用一些特定的元字符来检索、匹配以及替换符合规则的字符串。 构造正则表达式语法的元字符,由普通字符、标准字符、限定字符(量词)、定位字符(边界字符)组成 普通字符 字母[…...
AD(Altium Designer)更换PCB文件的器件封装
一、确定是否拥有想换的器件PCB封装 1.1 打开现有的原理图 1.2 确定是否拥有想换的器件PCB文件 1.2.1 如果有 按照1.3进行切换器件PCB封装 1.2.2 如果没有 按照如下链接进行添加 AD(Altium Designer)已有封装库的基础上添加器件封装-CSDN博客https://blog.csdn.net/XU15…...
【文献研究】含硼钢中BN表面偏析对可镀性的影响
《B 添加钢的溶融 Zn めっき性に及ぼす BN 表面析出の影響》由JFE公司田原大輔等人撰写。研究聚焦 B 添加钢在低露点退火时 BN 形成对镀锌性的影响,对汽车用高强度钢镀锌工艺优化意义重大。通过多组对比实验,结合多种分析手段,明确了相关因素…...
React学习-css
W3Schools Tryit Editor CSS 教程 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明: p { /* 这是个注释 */ color:red; text-align:center; }选择器 CSS Id: #para1{ text-align:center; color:red; } Class: .center {text-align:center;} p…...
AIP-215 API特定proto
编号215原文链接AIP-215: API-specific protos状态批准创建日期2018-10-01更新日期2018-10-01 API通常使用API特定proto定义,偶尔依赖通用组件。保持API相互隔离可以避免版本问题和客户端库打包问题。 指南 所有特定于某个API的protos 必须 位于带有主版本号的包…...
C++ 获取一整行(一行)字符串并转换为数字
代码很简单,主要是自己总是忘记,记录一下: #include <iostream> #include <cstdlib> #include <cstring>#include <string> #include <vector> #include <sstream>using namespace std;void print_int_…...
数据分析-Excel-学习笔记Day1
Day1 复现报表聚合函数:日期联动快速定位区域SUMIF函数SUMIFS函数环比、同比计算IFERROR函数混合引用单元格格式总结汇报 拿到一个Excel表格,首先要看这个表格的构成(包含了哪些数据),几行几列,每一列的名称…...
树莓派PICO 设备烧录成cmsis dap
文章目录 1. 实际操作2. IO连接 1. 实际操作 2. IO连接...
【数据结构】图的存储
目录 邻接矩阵 表示方法 代码定义 结构特点与度的信息 邻接表 表示方法 代码定义 结构特点与度的信息 十字链表 表示方法 第二步,将顶点x的firstIn域与所有headvex域为x的弧连起来。 结构特点与度的信息 邻接多重表 表示方法 结构特点与度的信息 图…...
如何解决uniapp打包安卓只出现功能栏而无数据的问题
如何解决uniapp打包安卓只出现功能栏而无数据的问题 经验来自:关于Vue3中调试APP触发异常:exception:white screen cause create instanceContext failed,check js stack -> at useStore (app-service.js:2309:15)解决方案 - 甲辰哥来帮你算命 - 博客…...
kotlin,数字滚动选择
用国内的通义灵码和codegeex都没有弄出来,最后只得用墙外的chatgpt才弄出一个满意的。kotlin真的有点难,好在有AI,让学习没这难了。 package com.example.mynumsetimport android.os.Bundle import androidx.activity.ComponentActivity imp…...
【4】搭建k8s集群系列(二进制部署)之安装master节点组件(kube-apiserver)
一、下载k8s二进制文件 下载地址: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG -1.20.md 注:打开链接你会发现里面有很多包,下载一个 server 包就够了,包含了 Master 和 Worker Node 二进制文件。…...
每日c/c++题 备战蓝桥杯(小球反弹)[镜像思路求解,最小公倍数]
思路: 错解:对于这道题而言,有的同学会选择用计算每次碰撞的坐标,直到坐标等于原点的方法来做,但这种方法实现起来比较繁琐,并且由于碰撞点的坐标有可能是浮点数,而浮点数会丢失精度࿰…...
