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

相关推荐
花花鱼1 小时前
android studio 设置让开发更加的方便,比如可以查看变量的类型,参数的名称等等
android·ide·android studio
alexhilton3 小时前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
AirDroid_cn6 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治6 小时前
手机电工仿真软件更新了
android
xiangzhihong89 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿10 小时前
基于Android14的CarService 启动流程分析
android
没有了遇见10 小时前
Android 渐变色实现总结
android
雨白13 小时前
Jetpack系列(四):精通WorkManager,让后台任务不再失控
android·android jetpack
mmoyula15 小时前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发
sam.li16 小时前
WebView安全实现(一)
android·安全·webview