简析 Kotlin 内联函数:与inline相关的关键字

我们知道 inline 函数的作用是可以在调用处替换为函数体实现,可以减少函数调用栈的使用,从而提升效率,本文会一起看看跟 inline 一起配合使用的几个关键字

0x00 inline + reified

在Kotlin中经常会看到一些内联函数是配合 reified 关键字使用

  • 保留运行时的类型
  • 原理是在调用处将范型替换为实际类型
kotlin 复制代码
inline fun <T> checkType(obj: Any) {
    if (obj is T) { // ❌ 这里会编译出错!
				println("${obj} 是 ${T::class.simpleName} 类型")
		}
}
kotlin 复制代码
// 添加 reified 关键字(必须配合 inline 使用)
inline fun <reified T> checkType(obj: Any) {
    if (obj is T) { // ✅ 现在可以了!
        println("${obj} 是 ${T::class.simpleName} 类型")
    }
}

// 使用示例
checkType<String>("Hello")  // 输出:Hello 是 String 类型
checkType<Int>("Text")      // 无输出,类型不匹配

简化Activity启动(无需传递Class参数)

kotlin 复制代码
// 使用 reified 的优雅方式
inline fun <reified T : Activity> Context.startActivity() {
    val intent = Intent(this, T::class.java) // 直接访问泛型类型的Class
    startActivity(intent)
}
// 调用 - 类型清晰,无需::class.java
startActivity<DetailActivity>()

Retrofit + reified 简化API响应处理

kotlin 复制代码
// 传统方式:需要传递Type
apiService.getUser().enqueue(object : Callback<User> {
    override fun onResponse(call: Call<User>, response: Response<User>) {
        // 处理响应
    }
})

// 使用 reified 的扩展函数
inline fun <reified T> Call<T>.enqueueSimplified(
    crossinline onSuccess: (T) -> Unit,
    crossinline onError: (Throwable) -> Unit
) {
    enqueue(object : Callback<T> {
        override fun onResponse(call: Call<T>, response: Response<T>) {
            if (response.isSuccessful) {
                onSuccess(response.body()!!)
            }
        }
        override fun onFailure(call: Call<T>, t: Throwable) {
            onError(t)
        }
    })
}

// 调用更加简洁
apiService.getUser().enqueueSimplified(
    onSuccess = { user -> showUser(user) },
    onError = { error -> showError(error) }
)

0x01 noinline:阻止内联

为什么需要它?当一个 Lambda 参数需要被存储传递 给其他非内联函数,或在非内联上下文中调用 时,就必须使用 noinline.

kotlin 复制代码
// 示例:需要存储 Lambda
inline fun doSomething(
    crossinline onStart: () -> Unit, // 这个会被内联
    noinline onComplete: () -> Unit   // 这个不会被内联
) {
    // 1. onStart 可以直接调用(内联)
    onStart()
    
    // 2. onComplete 需要被存储或传递
    val completionCallback = onComplete  // ✅ 可以存储,因为它是 noinline
    runLater(completionCallback)         // ✅ 可以传递给普通函数
    
    // 3. 尝试存储 onStart 会报错
    // val startCallback = onStart  // ❌ 错误:不能存储 crossinline lambda
}

// 一个普通(非内联)函数
fun runLater(callback: () -> Unit) {
    // 稍后执行...
}·

关键特性

  • 变为普通函数对象,有内存开销
  • 可以传递给其他非内联函数
  • 可以存储在变量或属性中
  • 不支持非局部返回(因为它已经不是内联的了)

0x02 crossinline:禁止非局部返回

作用 :允许 Lambda 被内联,但禁止在 Lambda 内部使用非局部返回 (即直接 return)。

为什么需要它?

当 Lambda 参数在另一个执行上下文中被调用时(如嵌套函数、另一个 Lambda),直接 return 会变得语义模糊,因此需要禁止

kotlin 复制代码
// 示例:Lambda 在嵌套上下文中执行
inline fun runInBackground(crossinline task: () -> Unit) {
    // 将 task 传递给另一个执行上下文
    Thread {
        task()  // 这里 task 是在新线程中执行,不是从 runInBackground 返回
    }.start()
}

fun testFunction() {
    runInBackground {
        println("在后台执行")
        // return  // ❌ 如果允许,这个 return 是要从 testFunction 返回,还是从 Lambda 返回?
        // 编译器禁止这种模糊的语义,必须使用:
        return@runInBackground  // ✅ 明确表示从 Lambda 返回
    }
    println("这行会被执行")
}

典型应用场景

kotlin 复制代码
// Android 中的 View.post 就是一个典型例子
public inline fun View.post(crossinline action: () -> Unit) {
    val runnable = Runnable { action() }  // action 在 Runnable 中执行
    handler.post(runnable)
}

// 使用
view.post {
    updateUI()
    // 不能直接 return,必须用 return@post
    if (condition) return@post  // ✅ 局部返回
}

场景:结合使用多个修饰符

kotlin 复制代码
inline fun processData(
    data: String,
    noinline validator: (String) -> Boolean, // 需要传递给普通函数
    crossinline onSuccess: (String) -> Unit, // 在回调中执行,禁止非局部返回
    onError: (Exception) -> Unit // 默认内联,允许非局部返回
) {
    // validator 被传递给普通函数
    if (!validateInput(data, validator)) {
        onError(IllegalArgumentException("无效数据"))
        return
    }
    
    // onSuccess 在异步回调中执行
    doAsyncWork(data) { result ->
        onSuccess(result)  // 这里禁止非局部返回
    }
}

fun validateInput(input: String, validator: (String) -> Boolean): Boolean {
    return validator(input)  // 普通函数接收 noinline lambda
}

0x03 核心总结

  1. noinline 是"功能开关":关闭内联,换取存储/传递能力
  2. crossinline 是"安全限制":保持内联,但禁止模糊的返回语义
  3. 默认行为是最灵活的:既内联又允许非局部返回,但限制最多
相关推荐
郝学胜-神的一滴4 分钟前
线程同步:并行世界的秩序守护者
java·linux·开发语言·c++·程序人生
好奇龙猫23 分钟前
【人工智能学习-AI-MIT公开课13.- 学习:遗传算法】
android·人工智能·学习
掉鱼的猫25 分钟前
灵动如画 —— 初识 Solon Graph Fluent API 编排
java·openai·workflow
TO_ZRG25 分钟前
Unity打包安卓、iOS知识点
android·unity·android studio
周杰伦fans27 分钟前
AndroidStudioJava国内镜像地址gradle
android·java·android-studio
艾莉丝努力练剑28 分钟前
【Linux进程控制(一)】进程创建是呼吸,进程终止是死亡,进程等待是重生:进程控制三部曲
android·java·linux·运维·服务器·人工智能·安全
2501_9240641129 分钟前
2026年移动应用渗透测试流程方案及iOS与Android框架对比
android·ios
用户693717500138432 分钟前
谷歌官方推荐:Android 性能优化全攻略——从工具到实战,两周提升 App 评分
android·android studio·android jetpack
顾林海33 分钟前
Android Profiler实战宝典:揪出CPU耗时元凶与内存泄露小偷
android·面试·性能优化