详解Kotlin 高阶函数 与 Lambda 表达式

 更新时间:2017年06月30日 14:57:52   投稿:lqh  
这篇文章主要介绍了详解Kotlin 高阶函数 与 Lambda 表达式的相关资料,需要的朋友可以参考下

详解Kotlin 高阶函数 与 Lambda 表达式

高阶函数(higher-order function)是一种特殊的函数, 它接受函数作为参数, 或者返回一个函数. 这种函数的一个很好的例子就是 lock() 函数, 它的参数是一个锁对象(lock object), 以及另一个函数, 它首先获取锁, 运行对象函数, 然后再释放锁:

fun <T> lock(lock: Lock, body: () -> T): T {
  lock.lock()
  try {
    return body()
  }finally {
    lock.unlock()
  }
}

上面的代码: body 参数是一个 函数类型: () -> T , 因此它应该是一个函数, 这个函数没有参数, 返回一个 T 类型的值。

高阶函数类似 C 语言的函数指针,高阶函数另一个例子:

fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
  val result = arrayListOf<R>()
  for (item in this)
    result.add(transform(item))
  return result
}

val doubled = ints.map { it -> it * 2 } // 调用

函数类型(Function Type)

对于接受另一个函数作为自己参数的函数, 我们必须针对这个参数指定一个函数类型, 例如前面例子的 map 函数,参数 transform 的类型是 (T) -> R, 意思是它是一个函数,参数 T, 返回 R。

引用以及返回一个函数

高阶函数可以接受函数参数,也可以返回一个函数引用, 函数可以赋值给变量,和 C 语言的函数指针一样。

fun bar(): (String) -> String = { str -> str.reversed() }

val reversi = bar()
reversi("hello")
reversi("world")

内联函数(Inline Function)

Kotlin 支持内联函数,函数内联也许会导致编译产生的代码尺寸变大, 但如果我们使用合理(不要内联太大的函数), 可以换来性能的提高。

inline fun foo() {
  //
}

如果一个内联函数的参数中有多个 Lambda 表达式, 而你只希望内联其中的一部分, 你可以对函数的一部分参数添加 noinline 标记。

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
  // ...
}

Lambda 表达式

Lambda 表达式的完整语法形式,如:

val sum = { x: Int, y: Int -> x + y }

Lambda 表达式包含在大括号之内, 在完整语法形式中, 参数声明在圆括号之内, 参数类型的声明可选, 函数体在 -> 符号之后. 如果 Lambda 表达式自动推断的返回值类型不是 Unit , 那么 Lambda 表达式函数体中, 最后一条(或者就是唯一一条)表达式的值, 会被当作整个 Lambda 表达式的返回值。

很多情况下 Lambda 表达式只有唯一一个参数. 如果 Kotlin 能够自行判断出 Lambda 表达式的参数定义,那么它将允许我们省略唯一一个参数的定义, 并且会为我们隐含地定义这个参数, 使用的参数名为 it :

ints.filter { it > 0 }

使用 带标签限定的 return 语法, 我们可以在 Lambda 表达式内明确地返回一个结果值. 否则, 会隐含地返回 Lambda 表达式内最后一条表达式的值。

ints.filter {
  val shouldFilter = it > 0
  return@filter shouldFilter
}

匿名函数(Anonymous Function)

匿名函数看起来与通常的函数声明很类似, 区别在于省略了函数名。

fun(x: Int, y: Int): Int = x + y

参数和返回值类型的声明与通常的函数一样, 但如果参数类型可以通过上下文推断得到, 那么类型声明可以省略:

ints.filter(fun(item) = item > 0)

闭包

所谓闭包,就是一个代码块可以访问外层作用域的变量和参数,例如上面提到的 Lambda 表达式和匿名函数。

var containsNegative = false
val ints = listOf(0, 1, 2, 3, 4, 5)
ints.forEach {
  if (it < 0)
  containsNegative = true
}


感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

相关文章

  • Java中的递增i++与++i的实现原理详解

    Java中的递增i++与++i的实现原理详解

    这篇文章主要介绍了Java中的i++与++i的实现原理详解,在Java中,i++是一种常见的递增操作符,用于将变量i的值增加1,它是一种简洁且方便的方式来实现循环和计数功能,i++可以用于各种情况,本文来看一下其实现原理,需要的朋友可以参考下
    2023-10-10
  • Java设计模式之工厂方法模式详解

    Java设计模式之工厂方法模式详解

    工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂、具体工厂、抽象产品、具体产品
    2022-08-08
  • Java中Optional.of()方法及源码解析(非常详细!)

    Java中Optional.of()方法及源码解析(非常详细!)

    这篇文章主要给大家介绍了关于Java中Optional.of()方法及源码解析的相关资料,Java中java.util .Optional类的of()方法用于获得该Optional类中具有指定类型的指定值的一个实例,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • springboot使用外置tomcat启动方式

    springboot使用外置tomcat启动方式

    这篇文章主要介绍了springboot使用外置tomcat启动方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • java8实现list集合中按照某一个值相加求和,平均值等操作代码

    java8实现list集合中按照某一个值相加求和,平均值等操作代码

    这篇文章主要介绍了java8实现list集合中按照某一个值相加求和,平均值等操作代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • JAVA中的队列(Queue)详解

    JAVA中的队列(Queue)详解

    这篇文章主要介绍了JAVA中的队列(Queue)详解,队列是一种特殊的线性表,遵循先入先出、后入后出的基本原则,一般来说,它只允许在表的前端进行删除操作,需要的朋友可以参考下
    2023-07-07
  • Java数据类型之引用数据类型解读

    Java数据类型之引用数据类型解读

    这篇文章主要介绍了Java数据类型之引用数据类型,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java 数据结构之删除链表中重复的结点

    Java 数据结构之删除链表中重复的结点

    在一个排序的链表中,会存在重复的结点,如何实现删除该链表中重复的结点,重复的结点不保留,并返回链表头指针呢?接下来小编将带你详细介绍
    2021-12-12
  • springboot集成开发实现商场秒杀功能

    springboot集成开发实现商场秒杀功能

    这篇文章主要介绍了springboot集成实现商品秒杀功能,秒杀系统业务流程,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • java8 多个list对象用lambda求差集操作

    java8 多个list对象用lambda求差集操作

    这篇文章主要介绍了java8 多个list对象用lambda求差集操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09

最新评论