Kotlin 函数引用

一、基本概念与语法

Kotlin 函数引用(Function Reference)通过双冒号操作符 :: 实现,允许将具名函数作为‌高阶函数的参数或返回值 ‌使用,其本质是将函数转换为‌函数类型实例‌‌14。

kotlin 复制代码
fun sum(x: Int, y: Int) = x + y
val sumRef: (Int, Int) -> Int = ::sum  // 函数引用赋值给变量‌:ml-citation{ref="4" data="citationList"}

二、核心使用场景

  1. 替代 Lambda 表达式

    当 Lambda 仅调用单一具名函数时,可用函数引用简化代码,提升可读性‌46:

    erlang 复制代码
    listOf(1, 3, 5).forEach(::println)  // 替代 { x -> println(x) }‌:ml-citation{ref="3" data="citationList"}
  2. 动态传递函数逻辑

    函数引用可作为参数传递给高阶函数,实现灵活的行为控制:

    kotlin 复制代码
    fun applyOp(x: Int, y: Int, op: (Int, Int) -> Int) = op(x, y)
    applyOp(2, 3, ::sum)  // 输出 5‌:ml-citation{ref="4" data="citationList"}
  3. 构建函数工厂

    函数类型作为返回值时,可基于条件返回不同函数引用:

    kotlin 复制代码
    fun getMathOp(isAdd: Boolean): (Int, Int) -> Int = 
        if (isAdd) ::sum else ::subtract‌:ml-citation{ref="1" data="citationList"}

三、不同引用类型的语法

引用类型 语法示例 说明
类静态方法 MyClass::methodName 需类名限定,参数包含类实例‌35
实例方法 myInstance::methodName 绑定实例,调用时无需传递接收者‌35
扩展函数 String::isEmpty 接收者类型作为第一个参数‌34
构造函数 ::MyClass 生成类实例的工厂函数‌5

四、注意事项与最佳实践

  1. 类型匹配严格性

    函数引用需与目标函数类型完全匹配(参数数量、类型、返回值),否则编译报错‌46。

    sql 复制代码
    // 错误:sum 函数类型为 (Int, Int) -> Int,与 (Int) -> Int 不匹配
    val invalidRef: (Int) -> Int = ::sum  
  2. 反射依赖库问题

    若需通过反射获取函数引用元信息(如 KFunction),需添加 kotlin-reflect 依赖‌5。

  3. 性能优化建议

    • 优先使用函数引用替代匿名类或反射调用;
    • 高频调用的场景可结合 inline 关键字消除 Lambda 开销‌6。

五、综合示例

kotlin 复制代码
kotlinCopy Code
// 类方法引用
class Logger(val tag: String) {
    fun log(msg: String) = println("$tag: $msg")
}
val logger = Logger("App")
val logRef: (String) -> Unit = logger::log  // 绑定实例的引用‌:ml-citation{ref="3,5" data="citationList"}

// 扩展函数引用
fun String?.safeIsEmpty(): Boolean = this.isNullOrEmpty()
val isEmptyRef: (String?) -> Boolean = String?::safeIsEmpty‌:ml-citation{ref="3,4" data="citationList"}

// 函数引用作为返回值
fun createComparator(reverse: Boolean): Comparator<Int> = 
    if (reverse) ::compareDescending else ::compareAscending‌:ml-citation{ref="6" data="citationList"}

案例

kotlin 复制代码
const val LOGIN_NAME1 = "xingmo"
const val LOGIN_PWD2 = "123456"

fun main(){
    login("xingmo","123456",::methodResponseResult) //实例方法的引用
    login("xingmo","123456",obj2)

    logRef.invoke("Hello")
}

// 类方法引用
class Logger(val tag: String) {
    fun log(msg: String) = println("$tag: $msg")
}
val logger = Logger("App")
val logRef: (String) -> Unit = logger::log  // 绑定实例的引用‌:ml-citation{ref="3,5" data="citationList"}

val obj1 = :: methodResponseResult //函数引用赋值给变量
val obj2 = obj1
//函数实现部分
fun methodResponseResult(msg: String, code: String) {
    println("最终登录的成果是:msg:$msg, code:$code")
}
const val USER_NAME_SAVE_DB4 = "xingmo"
const val USER_PWD_SAVE_DB4= "123456"

inline fun login(name: String, pwd: String, responseResult: (String, String) -> Unit) {
    if (USER_NAME_SAVE_DB4 == name && USER_PWD_SAVE_DB4 == pwd) {
        // 登录成功
        // 做很多的事情 校验成功信息等
        responseResult("登录成功", 200)
        // ...
    } else {
        // 登录失败
        // 做很多的事情 登录失败的逻辑处理
        // ...
        responseResult("登录失败错了", 444)
    }
}

总结 ‌:Kotlin 函数引用通过 :: 操作符实现函数逻辑的‌一级公民化‌,适用于代码简化、动态逻辑分发等场景,需注意类型匹配和性能优化‌

相关推荐
seabirdssss11 分钟前
Appium 在小米平板上的安装受限与闪退排查
android·appium·电脑
喂_balabala17 分钟前
Kotlin-属性委托
android·开发语言·kotlin
空中海25 分钟前
第一章:Android 系统架构与核心原理
android·系统架构
lI-_-Il1 小时前
适配工具箱:手机里的全能数字瑞士军刀
android·音视频
彳亍走的猪1 小时前
Android 全局防抖/防重复点击
android·java·开发语言
程序员陆业聪1 小时前
Android图片加载框架深度对比:Coil 3.4.0 vs Glide 5.0,该选哪个?
android
seabirdssss1 小时前
Android 模拟器搭建
android·经验分享
CYRUS STUDIO1 小时前
Frida 源码编译全流程:自己动手编译 frida-server
android·安全·逆向
程序员陆业聪2 小时前
Android内存优化:当LeakCanary遇上协程,内存泄漏治理进入新阶段
android
黄林晴2 小时前
解放双手!Android 发布官方 6 大技能,一键搞定迁移、优化、适配
android