欢迎来到CL境外营销平台,平台经营Instagram、Facebook、YouTube、TIKTOK、Twitter粉丝、点赞、播放量服务、客服微信:coolfensi 24小时在线欢迎咨询购买!
公告:
欢迎来到CL境外营销平台,平台经营Instagram、Facebook、YouTube、TIKTOK、Twitter粉丝、点赞、播放量服务、客服微信:coolfensi 24小时在线欢迎咨询购买!

Twitter上有趣的代码

首页 Twitter   作者:coolfensi  2023年01月29日  热度:243  评论:0     
时间:2023-1-29 20:07   热度:243° 

全文分为视频版文字版

  • 文字版: 文字侧重细节和深度,有些知识点,视频不好表达,文字描述的更加准确
  • 视频版:视频以动画的形式会更加的直观,看完文字版,在看视频,知识点会更加清楚,

这是海外一位 Kotlin GDE 大佬,在 Twitter 上分享的一段代码,我觉得非常的有意思,代码如下所示,我们花 10s 思考一下,输出结果是什么。

funprintE()={println("E")}funmain(){if(true)println("A")if(true){println("B")}if(true){{println("C")}}{println("D")}printE()when{true->{println("F")}}}

在 Twitter 评论区中也能看到很多不同的答案。

实际上最后输出结果如下所示。

ABF

不知道你第一次看到这么多混乱的花括是什么感觉,当我第一次看到这段代码的时候,我觉得非常的有意思。

如果在实际项目中有小伙伴这么嵌套花括号,我相信肯定会被拉出去暴晒。但是细心观察这段代码,我们能学习到很多 Kotlin 相关的知识点,我们先来说一下为什么最后输出的结果是A B F

下面图中红色标注部分,if表达式、when ... case表达,如果表达式内只有一行代码的话,花括号是可以省略的,程序执行到代码位置会输出对应的结果, 即A B F

那为什么C D E没有打印,因为图中绿色部分是lambda表达式,在 Kotlin 中lambda表达式非常的自由,它可以出现在很多地方比如方法内、if表达式内、循环语句内、甚至赋值给一个变量、或者当做方法参数进行传递等等。

lambda表达式用花括号包裹起来,用箭头把实参列表和lambda函数体分离开来,如下所示。

{x:Int->println("lambda 函数体")}

如果没有参数,上面的代码可以简写成下面这样。

{println("lambda 函数体")}

C D E的输出语句在lambda函数体内,lambda表达式我们可以理解为高阶函数,在上面的代码中只是声明了这个函数,但是并没有调用它,因此不会执行,自然也就不会有任何输出。现在我将上面的代码做一点点修改,在花 10s 思考一下输出结果是什么。

funprintE()={println("E")}funmain(){if(true)println("A")if(true){println("B")}if(true){{println("C")}()}{println("D")}()printE()()when{true->{println("F")}}}

最后的输出结果是:

ABCDEF

应该有小伙伴发现了我做了那些修改,我只是在lambda表达式后面加了一个(),表示执行当前的lambda表达式,所以我们能看到对应的输出结果。如下图所示,

lambda表达式最终会编译成FunctionN函数,如下图所示。

如果没有参数会编译成Function0,一个参数编译成Function1,以此类推。FunctionN重载了操作符invoke。如下图所示。

因此我们可以调用invoke方法来执行lambda表达式。

{println("lambda 函数体")}.invoke()

当然 Kotlin 也提供了更加简洁的方式,我们可以使用()来代替invoke(),最后的代码如下所示。

{println("lambda 函数体")}()

到这里我相信小伙伴已经明白了上面代码输出的结果,但是这里隐藏了一个有性能损耗的风险点,分享一段我在实际项目中见到的代码,示例中的代码,我做了简化。

funmain(){valcount=2(1..10).forEach{value->calculate(value){result->valaverage=result/countprintln(average)}}}funcalculate(x:Int,lambda:(result:Int)->Unit){lambda(x+10)}

上面的代码其实存在一个比较严重的性能问题,我们看一下反编译后的代码。

每次在循环中都会创建一个FunctionN的对象,那么如何避免这个问题,我们可以将lambda表达式放在循环之外,这样就能保证只会创建一个FunctionN对象,我们来看一下修改后的代码。

funcalculate(x:Int,lambda:(result:Int)->Unit){lambda(x+10)}funmain(){valcount=2vallambda:(result:Int)->Unit={result->valaverage=result/countprintln(average)}(1..10).forEach{value->calculate(value,lambda)}}

全文到这里就结束了,感谢你的阅读,坚持原创不易,欢迎在看、点赞、分享给身边的小伙伴,我会持续分享原创干货!!!


近期必读热门文章