Twitter 上有趣的代码
hi
这是 dhl
的第 73 篇原创文章个人微信: hi-dhl
Hi 大家好,我是 DHL。公众号:ByteCode ,专注分享有趣硬核原创内容,Kotlin、Jetpack、性能优化、系统源码、算法及数据结构、动画、大厂面经
这是海外一位 Kotlin GDE 大佬,在 Twitter 上分享的一段代码,我觉得非常的有意思,代码如下所示,我们花 10s 思考一下,输出结果是什么。
fun printE() = { println("E") }fun main() {
if (true) println("A")
if (true) { println("B") }
if (true) {
{ println("C") }
}
{ println("D") }
printE()
when {
true -> { println("F") }
}
}
在 Twitter 评论区中也能看到很多不同的答案。
实际上最后输出结果如下所示。
AB
F
不知道你第一次看到这么多混乱的花括是什么感觉,当我第一次看到这段代码的时候,我觉得非常的有意思。
如果在实际项目中有小伙伴这么嵌套花括号,我相信肯定会被拉出去暴晒。但是细心观察这段代码,我们能学习到很多 Kotlin 相关的知识点,我们先来说一下为什么最后输出的结果是 A B F
。
下面图中红色标注部分,if
表达式、 when ... case
表达,如果表达式内只有一行代码的话,花括号是可以省略的,程序执行到代码位置会输出对应的结果, 即 A B F
。
那为什么 C D E
没有打印,因为图中绿色部分是 lambda
表达式,在 Kotlin 中 lambda
表达式非常的自由,它可以出现在很多地方比如方法内、 if
表达式内、循环语句内、甚至赋值给一个变量、或者当做方法参数进行传递等等。
lambda
表达式用花括号包裹起来,用箭头把实参列表和 lambda
函数体分离开来,如下所示。
如果没有参数,上面的代码可以简写成下面这样。
{ println("lambda 函数体") }而 C D E
的输出语句在 lambda
函数体内, lambda
表达式我们可以理解为高阶函数,在上面的代码中只是声明了这个函数,但是并没有调用它,因此不会执行,自然也就不会有任何输出。现在我将上面的代码做一点点修改,在花 10s 思考一下输出结果是什么。
fun main() {
if (true) println("A")
if (true) { println("B") }
if (true) {
{ println("C") }()
}
{ println("D") }()
printE()()
when {
true -> { println("F") }
}
}
最后的输出结果是:
AB
C
D
E
F
应该有小伙伴发现了我做了那些修改,我只是在 lambda
表达式后面加了一个 ()
,表示执行当前的 lambda
表达式,所以我们能看到对应的输出结果。如下图所示,
lambda
表达式最终会编译成 FunctionN
函数,如下图所示。
如果没有参数会编译成 Function0
,一个参数编译成 Function1
,以此类推。FunctionN
重载了操作符 invoke
。如下图所示。
因此我们可以调用 invoke
方法来执行 lambda
表达式。
当然 Kotlin 也提供了更加简洁的方式,我们可以使用 ()
来代替 invoke()
,最后的代码如下所示。
到这里我相信小伙伴已经明白了上面代码输出的结果,但是这里隐藏了一个有性能损耗的风险点,分享一段我在实际项目中见到的代码,示例中的代码,我做了简化。
fun main() {(1..10).forEach { value ->
calculate(value) { result ->
println(result)
}
}
}
fun calculate(x: Int, lambda: (result: Int) -> Unit) {
lambda(x + 10)
}
上面的代码其实存在一个比较严重的性能问题,我们看一下反编译后的代码。
每次在循环中都会创建一个 FunctionN
的对象,那么如何避免这个问题,我们可以将 lambda
表达式放在循环之外,这样就能保证只会创建一个 FunctionN
对象,我们来看一下修改后的代码。
val lambda: (result: Int) -> Unit = { result ->
println(result)
}
(1..10).forEach { value ->
calculate(value, lambda)
}
}
全文到这里就结束了,感谢你的阅读,坚持原创不易,欢迎 在看、点赞、分享 给身边的小伙伴,我会持续分享原创干货!!!
推荐阅读:
公众号:ByteCode ,分享有用、有趣的硬核原创内容,Kotlin、Jetpack、性能优化、系统源码、算法及数据结构、动画、大厂面经。
👇🏻 真诚推荐你关注我👇🏻
因微信公众号更改了推送机制
可能无法及时看到最新文章
将公众号设为 星标
或常为文章点 在看
即可及时收到最新文章
欢迎前往 博客 查看更多 Kotlin、Jetpack 、动画算法图解、系统源码分析等等文章。以及开源项目、LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程 题解。
https://www.hi-dhl.com