内联函数
1、内联函数
使用高阶函数带来了响应的运行时麻烦:**每个函数都是一个对象,它捕获闭包,即这些变量可以在函数体内被访问,减少了内存:**毕竟内存的分配,虚拟调用的运行都会带来开销
但是大多数开销都可以用**内联函数inline
**避免
内联函数具体的在之前讲到了,这边就不细讲,就单纯的写两个例子
//内联函数
inline fun <T> addStringTest(test1:T,inlined:(T,T)->T):T {
return inlined(test1,test1)
}
infix fun String.addString(s:String):String=this+s
println(addStringTest("zhe shi inline fun") { s1, s2 ->s1 addString s2 })
输出结果
zhe shi inline funzhe shi inline fun
2、非内联函数
前面有说这里也就给个例子
//非内联函数
inline fun <T> addStringNoLine(test1: T,inlined: (T, T) -> T,noinline noinlined:(t:T)->T ):T{
return test1 sum inlined(noinlined(test1),test1)
}
infix fun <T> T.sum(t:T):T{
return t
}
println(addStringNoLine("this is boy",{t1,t2->"$t1+$t2"}){it.toUpperCase()})
输出结果
THIS IS BOY+this is boy
返回到非局部
在kotlin中,我们可以不加条件的使用return
去推出一个命名函数或表达式函数。这意味着推出一个lambda
函数,我们不得不使用标签,而且空白的return
在lambda函数中是禁止,因为lambda函数不可以造一个闭合函数返回:
返回到非局部 ??
在kotlin中,我们可以不加条件的使用return
去退出一个明明函数或者表达式函数。这意味着退出一个lambda函数,我们不得不使用标签,而且空白的return
在lambda函数中是禁止的,因为lambda函数不可以在一个闭合函数中返回
错误事例
//返回到非局部的错误事例
fun testLocalError(){
labdTest{
return //错误,在lambda函数中不可以在闭合函数中返回
}
}
fun labdTest(test:()->Int){
test()
}
正确做法应该是返回
//返回到非局部的错误事例
fun testLocalError(){
labdTest{
return@labdTest //错误,在lambda函数中不可以在闭合函数中返回
}
}
fun labdTest(test: () -> Unit){
test()
}
注意:lambda如果是内联传递的,则返回也是内联传递的,因此允许下面这样:
//返回到非局部
fun testLocal(){
inlineTest("ceshi"){
return
}
}
//内联函数
inline fun inlineTest(prefix: String, action: () -> Unit) {
println("call before $prefix")
action()
println("call after $prefix")
}
输出结果
call before ceshi
注意有些内联函数可以调用传递进来的lambda函数,但不是在函数体,而是在另一个执行的上下文中。需要有crossinline
注解才能???
crossinline:不允许非局部返回,强制设置为全局返回
一些内联函数可能调用传给它们的不是直接来自函数体、而是来自另一个执行上下文的 lambda 表达式参数,例如来自局部对象或嵌套函数。在这种情况下,该 lambda 表达式中也不允许非局部控制流。为了标识这种情况,该 lambda 表达式参数需要用 crossinline 修饰符标记。
//这个无法复现不知道具体原因,下方的代码能够实现
inline fun f(inlineOptions(InlineOption.ONLY_LOCAL_RETURN) body: () -> Unit) {
val f = object: Runnable {
override fun run() = body()
}
inline fun f(crossinline body: () -> Unit) {
val f = object : Runnable {
override fun run() = body()
}
}
实例化参数类型
在讲实例化参数类型之前我们必须明确一个修饰词的含义reified
reified
是什么
**reified
?*具体化,可以理解成具体化一个东西
//reified 实例化
inline fun <reified T> membersOf() = T::class.members
//测试reified实例化
// println(membersOf<Int>().joinToString { "\n" })
println(membersOf<StringBuilder>())
输出的话就是实例的对象内容
[fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.CharArray!, kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Double): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Float): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Long): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Any!): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.String!): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.CharArray!): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.CharSequence!): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.CharSequence!, kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Boolean): java.lang.StringBuilder!, fun java.lang.StringBuilder.insert(kotlin.Int, kotlin.Char): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Boolean): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.CharSequence!): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Char): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(java.lang.StringBuffer!): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.CharArray!): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.CharSequence!, kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Double): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.CharArray!, kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.String!): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Any!): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Long): java.lang.StringBuilder!, fun java.lang.StringBuilder.append(kotlin.Float): java.lang.StringBuilder!, fun java.lang.StringBuilder.deleteCharAt(kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.replace(kotlin.Int, kotlin.Int, kotlin.String!): java.lang.StringBuilder!, fun java.lang.StringBuilder.appendCodePoint(kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.delete(kotlin.Int, kotlin.Int): java.lang.StringBuilder!, fun java.lang.StringBuilder.reverse(): java.lang.StringBuilder!, fun java.lang.StringBuilder.indexOf(kotlin.String!, kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.indexOf(kotlin.String!): kotlin.Int, fun java.lang.StringBuilder.lastIndexOf(kotlin.String!, kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.lastIndexOf(kotlin.String!): kotlin.Int, fun java.lang.StringBuilder.toString(): kotlin.String, fun java.lang.StringBuilder.readObject(java.io.ObjectInputStream!): kotlin.Unit, fun java.lang.StringBuilder.writeObject(java.io.ObjectOutputStream!): kotlin.Unit, fun java.lang.StringBuilder.substring(kotlin.Int, kotlin.Int): kotlin.String!, fun java.lang.StringBuilder.substring(kotlin.Int): kotlin.String!, fun java.lang.StringBuilder.offsetByCodePoints(kotlin.Int, kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.append(java.lang.AbstractStringBuilder!): java.lang.AbstractStringBuilder!, fun java.lang.StringBuilder.chars(): java.util.stream.IntStream!, fun java.lang.StringBuilder.getChars(kotlin.Int, kotlin.Int, kotlin.CharArray!, kotlin.Int): kotlin.Unit, fun java.lang.StringBuilder.getValue(): kotlin.CharArray!, fun java.lang.StringBuilder.get(kotlin.Int): kotlin.Char, fun java.lang.StringBuilder.codePointBefore(kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.trimToSize(): kotlin.Unit, fun java.lang.StringBuilder.hashCode(): kotlin.Int, fun java.lang.StringBuilder.codePoints(): java.util.stream.IntStream!, fun java.lang.StringBuilder.codePointAt(kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.equals(kotlin.Any?): kotlin.Boolean, fun java.lang.StringBuilder.capacity(): kotlin.Int, fun java.lang.StringBuilder.setLength(kotlin.Int): kotlin.Unit, fun java.lang.StringBuilder.codePointCount(kotlin.Int, kotlin.Int): kotlin.Int, fun java.lang.StringBuilder.ensureCapacity(kotlin.Int): kotlin.Unit, fun java.lang.StringBuilder.setCharAt(kotlin.Int, kotlin.Char): kotlin.Unit, fun java.lang.StringBuilder.subSequence(kotlin.Int, kotlin.Int): kotlin.CharSequence, var java.lang.StringBuilder.value: kotlin.CharArray!, var java.lang.StringBuilder.count: kotlin.Int, val java.lang.StringBuilder.length: kotlin.Int, val serialVersionUID: kotlin.Long]
内联函数支持类型参数,并且需要类型实例化,所以和 reified何用能实例
我们用reified修饰符检查类型参数,因为函数是内联的,所以不虚反射,像!is
as
这样的操作都可以使用