rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • lambda

  • Kotlin 中的 Lambda 表达式和匿名函数有什么区别?
  • Android kotlin 替代 if...else... 语句,尾lambda写法

lambda

Kotlin 中的 Lambda 表达式和匿名函数有什么区别?

Lambda 表达式和匿名函数都是创建函数字面值的方式,但它们在语法和行为上有一些区别。

Lambda 表达式是最常用的方式,语法简洁,用花括号包围,参数和函数体用箭头分隔。Lambda 中的 return 语句会从包含它的函数返回,这是非局部返回(non-local return)。

匿名函数使用 fun 关键字但没有函数名,语法更像普通函数。匿名函数中的 return 只从匿名函数本身返回,这是局部返回(local return)。

// Lambda 表达式
val lambda = { x: Int, y: Int -> x + y }

// 匿名函数
val anonymousFunc = fun(x: Int, y: Int): Int {
    return x + y
}

// return 行为的区别
fun testLambda() {
    val list = listOf(1, 2, 3, 4, 5)
    
    // Lambda:return 会从 testLambda 返回
    list.forEach {
        if (it == 3) return  // 从 testLambda 返回
        println(it)
    }
    println("这行不会执行")
}

fun testAnonymous() {
    val list = listOf(1, 2, 3, 4, 5)
    
    // 匿名函数:return 只从 forEach 返回
    list.forEach(fun(value: Int) {
        if (value == 3) return  // 只从这个匿名函数返回
        println(value)
    })
    println("这行会执行")  // 输出:1 2 4 5 这行会执行
}

在实际开发中,Lambda 表达式用得更多,因为语法更简洁。匿名函数主要用在需要明确的局部返回语义的场景,或者需要显式指定返回类型的场景。

  1. 标签返回解决 Lambda 的返回问题

如果想在 Lambda 中实现局部返回,可以使用标签。给 Lambda 加上标签,然后用 return@标签 的方式返回。这样就不需要用匿名函数了。

fun testLabeledReturn() {
    val list = listOf(1, 2, 3, 4, 5)
    
    // 使用标签返回
    list.forEach label@{
        if (it == 3) return@label  // 只从 Lambda 返回
        println(it)
    }
    println("这行会执行")
    
    // 隐式标签(函数名)
    list.forEach {
        if (it == 3) return@forEach  // 使用函数名作为标签
        println(it)
    }
}
  1. 内联函数和非局部返回

Lambda 的非局部返回只在内联函数中允许。如果高阶函数没有 inline,Lambda 中不能使用非限定的 return。这是因为非内联函数的 Lambda 会被编译成类,无法从外层函数返回。这种限制保证了代码的正确性。

// 内联函数允许非局部返回
inline fun inlineFunc(block: () -> Unit) {
    block()
}

// 非内联函数不允许
fun normalFunc(block: () -> Unit) {
    block()
}

fun test() {
    inlineFunc {
        return  // OK,因为是内联的
    }
    
    normalFunc {
        // return  // 编译错误
        return@normalFunc  // 必须用标签
    }
}
  1. 类型推断的差异

Lambda 表达式的类型推断更智能,通常不需要显式声明参数类型。匿名函数有时需要显式声明返回类型,特别是有多个返回路径时。

// Lambda 类型推断
val list = listOf(1, 2, 3)
val doubled = list.map { it * 2 }  // 类型自动推断

// 匿名函数可能需要显式类型
val result = list.map(fun(x): Int {  // 显式返回类型
    if (x > 2) return x * 2
    return x
})
  1. 选择使用哪种方式

在实际开发中,大部分情况用 Lambda 表达式就够了,语法简洁、类型推断好。只有在以下情况考虑匿名函数:需要明确的局部返回语义、有多个返回路径、需要显式声明返回类型、代码逻辑复杂用 Lambda 不清晰时。在 Android 开发中,99% 的场景 Lambda 就足够了,匿名函数用得很少。

Android kotlin 替代 if...else... 语句,尾lambda写法

新建一个kt文件复制以下代码:

inline infix fun Boolean.trueLet(trueBlock: Boolean.() -> Unit): Else {
    if (this) {
        trueBlock()
        return NotDoElse(this)
    }
    return DoElse(this)
}

inline infix fun Boolean.falseLet(falseBlock: Boolean.() -> Unit): Else {
    if (!this) {
        falseBlock()
        return NotDoElse(this)
    }
    return DoElse(this)
}

interface Else {
    infix fun elseLet(elseBlock: Boolean.() -> Unit)
}

class DoElse(private val boolean: Boolean) : Else {
    override infix fun elseLet(elseBlock: Boolean.() -> Unit) {
        elseBlock(boolean)
    }
}

class NotDoElse(private val boolean: Boolean) : Else {
    override infix fun elseLet(elseBlock: Boolean.() -> Unit) {
    }
}

用法:

//原生写法
if (a > 1) {
    println("执行操作")
}
//替代if写法
(a > 1).trueLet { println("执行操作") }

//原生写法
if (a != 1) {
    println("执行操作")
}
//替代if写法
(a == 1).falseLet { println("执行操作") }

//原生写法
if (a < 1) {
    println("执行true操作")
}else{
    println("执行else操作")
}

//替代if写法
(a < 1).trueLet { println("执行true操作") }.elseLet { println("执行else操作") }
最近更新:: 2026/4/2 20:07
Contributors: luokaiwen