Kotlin中匿名函数(又称为Lambda,或者闭包)的详解
Posted 路宇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kotlin中匿名函数(又称为Lambda,或者闭包)的详解相关的知识,希望对你有一定的参考价值。
博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家
👉点击跳转到教程
1、匿名函数
fun main()
/**
* 匿名函数:
* 1.定义时不取名字的函数,我们称之为匿名函数,匿名函数通常整体传递给其他函数,或者从其他函数返回。
* 2.匿名函数对Kotlin来说很重要,有了它,我们能够根据需要制定特殊的规则,轻松定制标准库里的内置函数
*/
val total = "Mississippi".count()
println(total)
var totals = "Mississippi".count( letter ->
letter == 's'
)
println(totals)
/**
* 函数类型与隐式返回
* 1.匿名函数也有类型,匿名函数可以当作变量赋值给函数类型变量,就像其他变量一样,
* 匿名函数就可以在代码里传递了。
* 变量有类型,变量可以等于函数,函数也会有类型。函数的类型,由传入的参数和返回值类型决定。
* 2.和具名函数一样,除了极少数情况外,匿名函数不需要return关键字来返回数据,匿名函数会隐式或自动返回函数体最后一行语句的结果。
*/
//变量的类型是一个匿名函数
val blessingFunction: () -> String
blessingFunction =
val holiday = "2023"
"Happy $holiday"
println(blessingFunction())
val share: () -> String =
val story = "励志的故事"
"分享$story"
println(share())
val max: () -> Int =
val number1 = 10
val number2 = 20
Math.max(number1, number2)
println(max())
/**
* 函数参数:
* 和具名参数一样,匿名函数可以不带参数,也可以带一个或多个任何类型的参数,需要带参数时,
* 参数的类型放在匿名函数的类型定义中,参数名则放在函数定义中。
*/
val enjoy: (String) -> String = name ->
"享受$name"
println(enjoy("编程"))
/**
* it关键字:
* 定义只有一个参数的匿名函数时,可以使用it关键字来表示参数名。
* 当你需要传入两个值参,it关键字就不能用了。
*/
val testIt: (String) -> String =
"$it 使用it参数"
println(testIt("测试"))
/**
* 类型推断一
* 1.定义一个变量时,如果把匿名函数作为变量赋值给它,就不需要显示指明变量类型了。
*/
val studyKotlin =
val content = "kotlin"
"study $content"
println(studyKotlin())
val today =
val date = 15
date + 5
println("今天$today()日")
/**
* 类型推断二
* 类型推断也支持带参数的匿名函数,但为了帮助编译器更准确地推断变量类型,匿名函数的参数名和参数类型必须有。
*/
val studyTime: (String, Int) -> String = content, time ->
val start = "今天"
"$start 学习 $content 在 $time 月"
println(studyTime("kotlin", 1))
val studyTime1 = content: String, time: Int ->
val start = "今天"
"$start 学习 $content 在 $time 月"
println(studyTime1("android", 1))
输出结果如下:
11
4
Happy 2023
分享励志的故事
20
享受编程
测试 使用it参数
study kotlin
今天20日
今天 学习 kotlin 在 1 月
今天 学习 Android 在 1 月
2、Lambda的概述
3、函数的参数是另一个函数
fun main()
/**
* 定义参数是函数的函数
* 函数的参数是另外一个函数
*/
val getDiscountWord = goodsName: String, hour: Int ->
val currentYear = 2023
"$currentYear年,双十一$goodsName促销倒计时:$hour小时"
showOnBoard("卫生纸", getDiscountWord)
var totals = "Mississippi".count( letter ->
letter == 's'
)
/**
* 简略写法
* 如果一个函数的Lambda参数排在最后,或者是唯一的参数,那么括住Lambda值参的一对圆括号就可以省略。
*/
val totalBrief = "Mississippi".count letter ->
letter == 's'
println(totalBrief)
val totalBriefs = "Mississippi".count
it == 's'
println(totalBriefs)
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String)
val hour = (1..24).shuffled().last()
println(getDiscountWords(goodsName, hour))
输出结果如下:
2023年,双十一卫生纸促销倒计时:20小时
4
4
4、简略写法
/**
* 简略写法
* 如果一个函数的Lambda参数排在最后,或者是唯一的参数,那么括住Lambda值参的一对圆括号就可以省略。
*/
fun main()
showOnBoard("卫生纸") goodsName: String, hour: Int ->
val currentYear = 2023
"$currentYear年,双十一$goodsName促销倒计时:$hour小时"
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String)
val hour = (1..24).shuffled().last()
println(getDiscountWords(goodsName, hour))
输出结果如下:
2023年,双十一卫生纸促销倒计时:18小时
5、函数内联
fun main()
val getDiscountWords = goodsName: String, hour: Int ->
val currentYear = 2023
"$currentYear年,双十一$goodsName促销倒计时:$hour 小时"
showOnBoard("卫生纸", getDiscountWords)
//内联函数
/**
* 1、lambda可以让你更灵活地编写应用,但是,灵活也是要付出代价的。
* 2、在JVM上,你定义的lambda会以对象实例的形式存在,JVM会为所有同lambda打交道的变量分配内存,这就产生了内存消耗。
* 更糟的是,lambda的内存开销会带来严重的性能问题。
* 幸运的是,kotlin有一种优化机制叫做内联,有了内联,JVM就不需要使用lambda对象实例了,因而避免了变量内存分配。哪里需要
* 使用lambda,编译器就会将函数体复制到哪里。
* 3、使用lambda的递归函数无法内联,因为会导致复制粘贴无限循环,编译会发出警告。
*/
private inline fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String)
val hour = (1..24).shuffled().last()
println(getDiscountWords(goodsName, hour))
输出结果如下:
2023年,双十一卫生纸促销倒计时:17 小时
6、函数引用
fun main()
/**
* 函数引用:
* 要把函数作为参数传给其他函数使用,除了传lambda表达式,kotlin还提供了其他方法
* 传递函数引用,函数引用可以把一个具名函数转换成一个值参,使用lambda表达式的地方
* 都可以使用函数引用。
*/
showOnBoard("牙膏", ::getDiscountWords)
private fun getDiscountWords(goodsName: String, hour: Int): String
val currentYear = 2023
return "$currentYear年,双十一$goodsName促销倒计时:$hour 小时"
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String)
val hour = (1..24).shuffled().last()
println(getDiscountWords(goodsName, hour))
7、函数类型作为返回值类型、以及闭包
fun main()
/**
* 函数类型也是有效的返回类型,也就是说可以定义一个能返回函数的函数
*/
var getConfigDiscountWords = configDiscountWords()
println(getConfigDiscountWords("沐浴露"))
/**
* 闭包:
* 1.在kotlin中,匿名函数能够修改并引用定义在自己的作用域之外的变量,
* 匿名函数引用着定义自身的函数里的变量,kotlin中的lambda就是闭包。
* 2.能接收函数或者返回函数的函数又叫做高级函数,高级函数广泛应用于函数式编程当中。
*
* 重点:闭包,lambda表达式,匿名函数,三者只是叫法不同。
*/
fun configDiscountWords(): (String) -> String
val currentYear = 2023
var hour = (1..24).shuffled().last()
return goodsName: String ->
"$currentYear年,双十一$goodsName促销倒计时:$hour 小时"
8、lambda表达式与匿名内部类
对比可以看出kotlin的简洁性,同样的逻辑
1、java代码
public class JavaAnonymousClass
public static void main(String[] args)
/**
* lambda与匿名内部类
* 为什么要在代码中使用函数类型?
* 1.函数类型能让开发者少写模式化代码,写出更灵活的代码
* 2.Java8支持面向对象编程和lambda表达式,但不支持将函数作为参数传递给另一个函数或者参数,
* 不过Java的替代方案是匿名内部类。
*/
showOnBoard("手机", new DiscountWords()
@Override
public String getDiscountWords(String goodsName, int hour)
int currentYear = 2027;
return String.format("%d年,双十一%s促销倒计时:%d小时", currentYear, goodsName, hour);
);
public interface DiscountWords
String getDiscountWords(String goodsName, int hour);
public static void showOnBoard(String goodsName, DiscountWords discountWords)
int hour = new Random().nextInt(24);
System.out.println(discountWords.getDiscountWords(goodsName, hour));
2、kotlin代码
fun main()
showOnBoard("卫生纸") goodsName: String, hour: Int ->
val currentYear = 2023
"$currentYear年,双十一$goodsName促销倒计时:$hour 小时"
private fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String)
val hour = (1..24).shuffled().last()
println(getDiscountWords(goodsName, hour))
以上是关于Kotlin中匿名函数(又称为Lambda,或者闭包)的详解的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin函数 ⑤ ( 匿名函数变量类型推断 | 匿名函数参数类型自动推断 | 匿名函数又称为 Lambda 表达式 )