学习kotlin第12天_lambda表达式 川长思鸟来 2022-06-14 02:22 182阅读 0赞 继续昨天的,从昨天的第14个坑开始。 坑1、以map为例。文档上为如下代码,调用时由于lambda表达式在圆括号以外,而圆括号中已无其它参数,故可以省略 fun <T, R> List<T>.map(transform: (T) -> R): List<R> { val result = arrayListOf<R>() for (item in this) result.add(transform(item)) return result } fun main(args: Array<String>) { var ints = arrayListOf(1, 2, 3) val doubled = ints.map( { value -> value * 2 }) println(doubled) } 在idea中该for循环提示 *Loop can be replaced with stdlib operations less... (Ctrl+F1)* *This inspection reports for-loops that can be replaced with a sequence of stdlib-operations (like "map", "filter" etc)* 按照提示修改为 fun <T, R> List<T>.map(transform: (T) -> R): List<R> { return this.map { transform(it) } } 发生了StackOverflowError。因为这两个map是不同的方法,this.map调用的应该是Collections.kt文件中的Iterable<T>.map方法而非当前map方法,改一下当前方法名即可。阅读源码可知该方法和源码几乎相同。 /** * Returns a list containing the results of applying the given [transform] function * to each element in the original collection. */ @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> { return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform) } /** * Applies the given [transform] function to each element of the original collection * and appends the results to the given [destination]. */ public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C { for (item in this) destination.add(transform(item)) return destination } 坑2 、如果lambda表达式的参数只有一个,则可以省略并用it代替。It在之前for循环的时候见到过,当时不知道it是什么,以为直接是这个集合的item呢,确实也是,但它大多是该方法通过for(item in this)得到的,然后作为lambda表达式的参数。 fun main(args: Array<String>) { var ints = arrayListOf(1, 2, 3) val doubled = ints.map { it * 2 } println(doubled) } 坑3 、下划线用于lambda中表示没用到的参数。 fun main(args: Array<String>) { var map = mapOf(1 to "one", 2 to "two") println(map.mapValues { (_, value) -> "$value" })//_代表没有用到的key } 坑4、高阶函数必须为函数类型的参数指定类型,该参数名可作为函数名使用。前面已经见到很多了,就不多说了。 坑5、可通过标签从lambda显示返回一个值,否则为最后一个表达式的值。 坑6、匿名函数作为参数时必须放在圆括号内,匿名函数与lambda表达式的区别是return时匿名函数从自身返回,而lambda表达式中的return将从包含它的函数返回。 坑7、kotlin的lambda表达式或者匿名函数(以及局部函数和对象表达式)可以访问外部作用域中声明的变量,类似于内部类。 坑8、类似于扩展函数,允许在函数体内访问接收者对象的成员而无需额外的限定符。匿名函数允许直接指定函数字面值的接收者类型。当接收者类型可以从上下文推断时,lambda 表达式可以用作带接收者的函数字面值。。。(晕乎乎的,没懂) class HTML { fun body() { println("body") } } fun html(init: HTML.() -> Unit): HTML { val html = HTML() // 创建接收者对象 html.init() // 将该接收者对象传给该 lambda return html } fun main(args: Array<String>) { html { // 带接收者的 lambda 由此开始 body() // 调用该接收者对象的一个方法 } } 坑9、内联函数能消除部分时间开销,减少部分效率损失,用inline标记。。。求清晰点的demo! 坑10、noline修饰部分参数内联,求解释!求demo! 坑11、前面说了lambda表达式中的 return 将从包含它的函数返回,现在又来一句lambda表达式不能使包含他的函数返回,除非设置为内联。谁能告诉我为什么?我有一种把所有文章都删掉的冲动!我在想,我到底是来踩坑的还是来浪费大家时间的? 坑12、这种位于lambda表达式中,但退出包含它的函数,称为非局部返回。(有一种似懂非懂的感觉) fun hasZeros(ints: List<Int>): Boolean { ints.forEach { if (it == 0) return true // 从 hasZeros 返回 } return false } 坑13、crossinline用来标记调用来自局部对象或者嵌套函数的内联函数。(看见demo也是懵逼的) inline fun f(crossinline body: () -> Unit) { val f = object: Runnable { override fun run() = body() } } 坑14、具体化的类型参数以及内联属性我已经无法描述出来了,神啊,救救我吧!
还没有评论,来说两句吧...