4.Demo-计算函数花费时间


// 计算函数执行的时间

fun cost(block: () -> Unit) {

val start = System.currentTimeMillis()

block()

println(“执行时间${System.currentTimeMillis() - start}ms”)

}

// 斐波那契数列

fun fibonacci(): () -> Long {

var start = 0L

var second = 1L

// 匿名函数 lambda表达式的表现形式

return {

val next = start + second

val current = start

start = second

second = next

current

}

}

// 使用

fun main() {

// 将lambda表达式移到最外面,省略小括号

cost {

val function = fibonacci()

for (i in 0…10) {

val longVal = function()

println(longVal)

}

}

}

二、kotlin内联函数

===============================================================================

1.内联函数概念


用inline关键字进行修饰,如果该函数接受一个匿名函数(lambda表达式),则可以使用inline关键字修饰改函数,然后接受的匿名函数会被编译器优化,内联到函数内部,会节省开销。

示例如下所示:

//内联函数

inline fun IntArray.forEatch(action:(Int)->Unit):Unit{

for(element in this) action(element)

}

//调用处

fun main(){

val ints = intArrayOf()

ints.forEach{

println(“hello$it”)

}

}

//实际编译之后的调用(大致)

fun main(){

val ints = intArrayOf()

for(element in this) {

println(“hello$element”)

}

}

上述所示,使用inline修饰之后,在编译期间kotlin会对代码调用栈进行优化。

2.高阶函数和内联函数


示例如下所示:

inline fun cost(block:()->Unit){

val start = System.currentTimeMillis()

block()

println(System.currentTimeMillis() - start)

}

//调用

cost{

println(“hello”)

}

//实际编译效果

val start = System.currentTimeMillis()

println(“hello”)

println(System.currentTimeMillis() - start)

高阶函数内联

  • 函数本身被内联到调用处

  • 函数的函数参数被内联到调用处

3.内联函数的限制以及详细说明


  • public/protected的内敛方法只能访问对应类的public成员(也可以理解,毕竟可以在编译期间优化到调用处,怎么访问私有属性呢)

  • 内联函数的内联函数参数不能被储存(赋值给变量)

  • 内联函数的内联函数参数只能传递给其他内联函数参数

另: 与inline一块配合使用的有noinline以及crossinline。关于内联函数的详细说明,以及这个三个参数的详细区别,可参考:kotlin:inline、noinline、crossinline还傻傻分不清楚?看这一篇就够了

三、kotlin几个常用的高阶函数let、run、also、apply、use

==========================================================================================================

1.let


let源码如下所示:

public inline fun <T, R> T.let(block: (T) -> R): R {

contract {

callsInPlace(block, InvocationKind.EXACTLY_ONCE)

}

return block(this)

}

注意:我们可以忽略掉contract契约检查(下面遇到的源码如包含contract,都可以进行忽略,且不在提及),那么核心的函数其实就是return block(this)

let : 将receiver作为参数传入block,并且返回block的返回值

简单使用实例如下所示:

val strLenght = arrayOf(“hello”, “world”).let {

it.joinToString(" ") { s: String ->

“$s length: ${s.length}”

}

}

println(strLenght)

//输出

hello length: 5 world length: 5

2.run


run源码如下所示:

public inline fun <T, R> T.run(block: T.() -> R): R {

contract {

callsInPlace(block, InvocationKind.EXACTLY_ONCE)

}

return block()

}

接收的block类型为T.() -> Unit 所以 block里面可使用this指代调用者

run : block里面可使用this指代调用者,并且返回block的返回值

简单使用实例如下所示:

val strLenght = arrayOf(“hello”, “world”).run {

this.joinToString(" ") { s: String ->

“$s length: ${s.length}”

}

}

println(strLenght)

//输出

hello length: 5 world length: 5

3.also


also源码如下所示:

public inline fun T.also(block: (T) -> Unit): T {

contract {

callsInPlace(block, InvocationKind.EXACTLY_ONCE)

}

block(this)

return this

}

和let的区别就是返回类型不一样了,block是无返回类型,整个函数返回调用者T

核心函数 block(this) return this

简单使用实例如下所示:

val arrayStr = arrayOf(“hello”, “world”).also {

val joinToString = it.joinToString(" ") { s: String ->

“$s length: ${s.length}”

}

println(joinToString)

}

println(arrayStr is Array)

//输出

hello length: 5 world length: 5

true

4.apply


apply源码如下所示:

public inline fun T.apply(block: T.() -> Unit): T {

contract {

callsInPlace(block, InvocationKind.EXACTLY_ONCE)

}

block()

return this

}

和run的区别就是返回类型不一样了,block是无返回类型,整个函数返回调用者T

核心函数 block() return this

简单使用实例如下所示:

val arrayStr = arrayOf(“hello”, “world”).apply{

val joinToString = it.joinToString(" ") { s: String ->

“$s length: ${s.length}”

}

println(joinToString)

}

println(arrayStr is Array)

//输出

hello length: 5 world length: 5

true

5.use


use源码如下所示:

public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {

contract {

callsInPlace(block, InvocationKind.EXACTLY_ONCE)

}

var exception: Throwable? = null

try {

return block(this)

} catch (e: Throwable) {

exception = e

throw e

} finally {

when {

apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)

this == null -> {}

exception == null -> close()

else ->

try {

close()

} catch (closeException: Throwable) {

// cause.addSuppressed(closeException) // ignored here

}

}

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-o5i0dMWB-1712531698698)]

自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

[外链图片转存中…(img-pnlMGaBw-1712531698698)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐