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 小时前
安卓adb shell串口基础指令
android·adb
fatiaozhang95273 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO4 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师5 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师5 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫5 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白5 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong7 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo030519878 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111228 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发