theme: channing-cyan 标准库函数
返回新的值 let 函数我按照返回值做了区分, 这样好理解, 如果标准函数返回的自己, 则我们可以做属于自己的的链式调用, 如果返回的是别人, 可以做别人的链式调用, 如果函数类型参数有扩展, 则可以使用this
let函数把this当作参数传递给lambda的参数, 然后返回lambda的返回值
val first = listOf(1, 2, 3).first()
val res = first * first
println(res)
println(listOf(1, 2, 3).first().let { it * it })
public inline fun返回新的值(函数类型参数带扩展) with 函数(不是扩展函数)T.let(block: (T) -> R): R { return block(this) }
val with = fun MutableList.(): Int { this[0] += 1 return this[0] } fun main() { val list = with(listOf(1, 2, 3)) { this.map { it + 1 } } println(list) println(mutableListOf(1, 2, 3).with()) // with(listOf(1, 2, 3)) }
with 函数第一个参数是传递接收者, 第二个参数传递的是 匿名扩展函数类型
上面的代码我写了个匿名扩展函数变量, 可以代替 with 函数, 而且使用方式很像
kotlin源码:
public inline funwith(receiver: T, block: T.() -> R): R { return receiver.block() }
with的使用场景block: T.() -> R的使用方法有两种, 第一种是 block(this) 这种方式调用, 还有一种就是 this.block() 的方式调用, 这两种都行, 第一种是我们跳过编译器主动传递 this 进去, 第二种是 编译器主动将接收者当作 参数 传递进去
const val letter: String = "abcdefghijklmnopqrstuvwxyz"
fun alphabet01(): String {
val stringBuilder = StringBuilder()
letter.forEach { stringBuilder.append(it.uppercaseChar()) }
stringBuilder.append("nNow I know the alphabet!")
return stringBuilder.toString()
}
使用 stringBuilder 对象本身数量有点多的时候, 可以考虑使用 with
fun alphabet02() = kotlin.with(StringBuilder()) {
letter.forEach { if (it in 'a'..'z') {
// append(it.minus('a').plus('A'.code).toChar())
append(it.uppercaseChar())
} }
append("nNow I know the alphabet!")
toString()
}
我们还可以使用 buildString, 它底层使用的还是 StringBuilder 所以这样可以这样:
fun alphabet03() = buildString {
for (c in letter) {
append(c.uppercaseChar())
}
append("n" +
"Now I know the alphabet!")
}
它在返回的时候, 返回的是 String 类型
StringBuilder().apply(builderAction).toString()
run 扩展函数val s = File("""D:test.txt""").run {
if (canRead()) reader().buffered().use { it.readText() } else null
}
println(s)
public inline funuse 扩展函数T.run(block: T.() -> R): R { return block() }
主要用于文件流操作, 帮助添加 try catch finally
val s = FileReader("""D:test.txt""").buffered().use {
it.readText()
}
println(s)
返回自己
also 扩展函数
also 支持链式调用
使用方法:
val file = File("""D:test.txt""").also {
println(it.name)
}.also {
// println(it.readLines())
println(it.readText())
}
kotlin also 底层函数:
public inline funtaskIf 扩展函数T.also(block: (T) -> Unit): T { block(this) return this }
如果满足 taskIf 的条件(为 true), 则返回 this , 否则 返回 null
val file = File("""D:test.txt""").takeIf {
it.canRead() && it.canWrite()
}
println(file)
public inline funT.takeIf(predicate: (T) -> Boolean): T? { return if (predicate(this)) this else null }
很简单, 函数参数 predicate , 使用 predicate 函数 , 传递 this 进入函数体中执行, 然后返回 boolean, 同 Boolean 判断 如果 为 true 则返回 this , 否则返回 false
这个也可以链式调用, 但是需要判断是否 可空 比较麻烦一点
taskUnless 扩展函数如果表达式不满足条件, 则返回 this, 否则返回 null
val file = File("""D:test.txt""").takeUnless {
it.isDirectory
}
println(file)
public inline funT.takeUnless(predicate: (T) -> Boolean): T? { return if (!predicate(this)) this else null }
withLock 线程锁扩展函数注意上面 takeIf 和 takeUnless 都返回的可空类型, T?
val l: Lock = ReentrantLock()
l.withLock {
// ...........
}
public inline fun返回自己(函数类型参数带扩展) apply 函数Lock.withLock(action: () -> T): T { lock() try { return action() } finally { unlock() } }
用法:
val file1 = File("""D:test.txt""")
file1.setWritable(true)
file1.setReadable(true)
file1.setExecutable(true)
val file2 = File("""D:test.txt""").apply {
setWritable(true)
setReadable(true)
setExecutable(true)
}
应用场景:
apply 类似于一个配置函数, 用于配置接收者, 然后再返回配置好的接收者
解析:
public inline funT.apply(block: T.() -> Unit): T { block() return this }
把接收者作为 T 带入 File.apply(block: File.() -> Unit): File , 我们解析一下:
- 他是 File 的扩展函数
- 他返回 File 对象本身
- 他传递一个 匿名扩展函数(带 this 参数的 lambda 表达式函数), 函数返回值为 Unit
这里需要注意一点, block 是 lambda 表达式, 把 lambda 表达式传递进另一个函数体内部, lambda就可以访问表达式外部函数体作用域能访问的所有东西, 这是闭包
在 idea 查找扩展函数的方法 安装 extSee 插件闭包就是能够读取其他函数内部变量的函数, 或者叫 定义在一个函数内部的函数, 这样函数体内部能够访问函数体外部的, 本质上,闭包是将函数内部和函数外部连接起来的桥梁
然后就能看到了
使用 idea 的 find usages不推荐, 这种方式查询出来的东西太多了, 不能够限定只查询 extension
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TIpa5UMp-1656299586587)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/233ee3a7759c4082b202ab0118822dc9~tplv-k3u1fbpfcp-watermark.image?)]
将函数内部和函数外部连接起来的桥梁
在 idea 查找扩展函数的方法 安装 extSee 插件然后就能看到了
[外链图片转存中…(img-n0PcYruw-1656299586585)]
[外链图片转存中…(img-DuPnalZq-1656299586586)]
使用 idea 的 find usages不推荐, 这种方式查询出来的东西太多了, 不能够限定只查询 extension
[外链图片转存中…(img-TIpa5UMp-1656299586587)]



