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

相关推荐
一笑的小酒馆5 小时前
Android在ksp中简单使用Room
android
meimeiqian6 小时前
flutter android端抓包工具
android·flutter
Android技术之家6 小时前
谷歌决定终止开源Android以及对开发者的影响
android·开源
每次的天空8 小时前
Android Jetpack学习总结(源码级理解)
android·学习·android jetpack
木子庆五8 小时前
Android设计模式之代理模式
android·设计模式·代理模式
在雨季等你8 小时前
创业之旅 - 反思 - 整改 - 新的方向 - 诚邀
android
Long_poem8 小时前
【自学笔记】PHP语言基础知识点总览-持续更新
android·笔记·php
fatiaozhang952710 小时前
晶晨S905L3A(B)-安卓9.0-开启ADB和ROOT-支持IPTV6-支持外置游戏系统-支持多种无线芯片-支持救砖-完美通刷线刷固件包
android·游戏·adb·华为·电视盒子·机顶盒rom·魔百盒固件
行墨10 小时前
Kotlin语言的==与===比较操作
android
圣火喵喵教11 小时前
Pixel 8 pro 刷AOSP源码 Debug 详细教程(含救砖)
android