kotlin内联函数_Kotlin内联函数,参数化

本文深入探讨Kotlin的内联函数,包括内联如何减少内存开销,允许非局部控制流,以及如何使用Reified Type Parameters。内联函数通过复制函数体到调用点,避免额外的对象创建,提升性能。同时,文章提到了`noinline`修饰符和内联属性的应用。
摘要由CSDN通过智能技术生成

kotlin内联函数

In this tutorial, we’ll be looking into Kotlin inline function. We’ll follow that with Reified Type Parameters.

在本教程中,我们将研究Kotlin内联函数。 我们将在后面加上Reified Type Parameters。

Kotlin内联函数 (Kotlin inline functions)

We’ve discussed Kotlin Higher Order Functions and Lambda Expressions before.
They’re super useful in passing functions as parameters. But these functions are objects which have there own callbacks and subsequently memory allocations. Let’s understand how these functions passed as parameters internally work through an example.

我们之前已经讨论过Kotlin高阶函数和Lambda表达式
在将函数作为参数传递时,它们非常有用。 但是这些函数是具有自己的回调以及随后的内存分配的对象。 让我们通过示例了解如何将这些函数作为参数传递给内部。

fun main(args: Array<String>) {

    println("Hey how are you doing")
    sampleFunction("JournalDev.com", ::println)
}

fun sampleFunction(str: String, expression: (String) -> Unit) {
    println("This is Kotlin Inline Functions Tutorial")
    expression(str)
}

sampleFunction when run passes println as the parameter. Now Kotlin is a JVM based language so everything is converted into bytecode. Let’s look at the bytecode of the above code by going to Tools | Kotlin | Show Bytecode.

运行时的sampleFunctionprintln作为参数传递。 现在Kotlin是一种基于JVM的语言,因此所有内容都将转换为字节码。 让我们通过转到“ 工具” |“工具栏” |查看上面代码的字节码。 Kotlin| 显示字节码

The main part expression.invoke(). Invoking the lambda expression (println) would create an additional call and hence memory. The invoke method looks like this in Java:

主要部分是expression.invoke() 。 调用lambda表达式(println)将创建一个附加调用,从而创建一个内存。 Java中的invoke方法如下所示:

expression(new Function() {
        @Override
        public void invoke() {
         //println statement is called here.

        }
    });

Now if we call multiple functions as parameters each of them would add up to the method count and have a HUGE impact on the memory and the performance.

现在,如果我们将多个函数作为参数调用,则每个函数将加总方法计数,并对内存和性能产生巨大影响。

Inline Functions to the rescue!

内联函数进行救援!

Inline functions flatten the function calls by providing the function body and everything to the calling function at runtime. We need to add the inline modifier to do so.
So the sampleFunction above would look like the below code when the sampleFunction is called.

内联函数通过在运行时向调用函数提供函数主体和所有内容,从而使函数调用变得平坦。 我们需要添加inline修饰符。
因此,当调用sampleFunction时,上面的sampleFunction看起来像下面的代码。

inline fun sampleFunction(str: String, expression: (String) -> Unit) {
    print("This is Kotlin Inline Functions Tutorial")
    expression(str)
}

inline keyword copies the function to the call site. This saves the additional object creation to invoke the parameter function thus saving memory for you.

inline关键字将功能复制到呼叫站点。 这样可以节省额外的对象创建来调用参数函数,从而为您节省内存。

Let’s look at the bytecode now by decompiling.

kotlin inline function bytecode

现在让我们通过反编译来查看字节码。

Take note: The println lambda expression is expanded in the main function itself in the form of System.out.println. NO more additional calls needed.

请注意println lambda表达式在main函数本身中以System.out.println的形式扩展。 不再需要其他电话。

Why not make every function inlined?

为什么不使每个函数都内联?

  • Inlining a function copies the code into one place thereby increasing the generated code. It should be avoided when the function to be invoked through parameter has a big code already.

    内联函数将代码复制到一个位置,从而增加了生成的代码。 当通过参数调用的函数已经具有较大的代码时,应避免使用。
  • Also, inlined functions can’t access private members of the enclosed class. You’ll have to set them as internal

    此外,内联函数无法访问封闭类的private成员。 您必须将它们设置为internal

An example using inline functions is given below:

下面是使用内联函数的示例:

fun main(args: Array<String>) {
    normalFunction()
}

fun normalFunction() {
    println("This is normal function.")
    inlineFunctionExample({ println("Inlined Functions")},{ println("Instead of object creation it copies the code.")} )
}

inline fun inlineFunctionExample(myFunction: () -> Unit, another: () -> Unit  ) {
    myFunction()
    another()
    print("Finally it's working fine!")
}

In the above code, we’ve passed many lambda expressions.
All of these would be copied at runtime.

在上面的代码中,我们传递了许多lambda表达式。
所有这些都将在运行时复制。

Following is the generated bytecode in our IntelliJ:

kotlin inline keyword

以下是我们的IntelliJ中生成的字节码:

All the println lambda calls are flattened in the normalFunction itself. The output takes lesser memory.

所有println lambda调用均在normalFunction自身中展平。 输出占用更少的内存。

内联允许非本地控制流 (Inline Allows Non-Local Control Flow)

With inline functions, you can return from the lambda expression itself and it’ll exit the function in which inline function was called. The below snippet demonstrates the same.

使用内联函数,您可以从lambda表达式本身返回,它将退出调用内联函数的函数。 下面的代码段演示了相同的内容。

fun main(args: Array<String>) {
    normalFunction()
}

fun normalFunction() {
    println("This is normal function.")
    inlineFunctionExample({ println("Inlined Functions")
        return},{ println("Instead of object creation it copies the code.")} )

    println("This is normal function closing")
}

inline fun inlineFunctionExample(myFunction: () -> Unit, another: () -> Unit  ) {
    myFunction()
    another()
    print("Finally it's working fine!")
}

The output that gets printed is :

输出的输出是:

As you can see, the inlined function is exited as well as its enclosing function.
We cannot return from lambda expressions that are a part of normal functions(non inline functions).

如您所见,内联函数及其封闭函数都已退出。
我们不能从作为普通函数(非内联函数)一部分的lambda表达式返回。

To prevent this, we can mark the lambda expression as crossinline. It’ll throw a compiler error if it sees a return statement inside that lambda expression.

为了防止这种情况,我们可以将lambda表达式标记为crossinline 。 如果在该lambda表达式中看到return语句,则会引发编译器错误。

fun normalFunction() {
    println("This is normal function.")
    inlineFunctionExample(
    { println("Inlined Functions")
        return //compiler error here
    },
    { println("Instead of object creation it copies the code.")}
    )

    println("This is normal function closing")
}

inline fun inlineFunctionExample(crossinline myFunction: () -> Unit, another: () -> Unit  ) {
    myFunction()
    another()
    print("Finally it's working fine!")
}

Noinline (noinline)

noinline modifier is used to set expressions not to be inlined in the call.

noinline修饰符用于设置在调用中不inlined表达式。

fun main(args: Array<String>) {
    normalFunction()
}

fun normalFunction() {
    println("This is normal function.")
    inlineFunctionExample({ println("Inlined Functions")},
            { println("Instead of object creation it copies the code.")} )

    println("This is normal function closing")
}

inline fun inlineFunctionExample(myFunction: () -> Unit, noinline another: () -> Unit  ) {
    myFunction()
    another()
    print("Finally it's working fine!")
}

anothernoinline expressions don’t support non-local control flow. Setting a return statement in them would throw a compiler error.

anothernoinline表达式不支持非本地控制流。 在它们中设置return语句将引发编译器错误。

内联属性 (Inline Properties)

Kotlin inline keyword is allowed on properties too. Just like inline functions, it’ll copy the inline properties accessor methods to the call site.
Inline properties cannot have a backing field.

属性还允许使用Kotlin内联关键字。 就像内联函数一样,它将内联属性访问器方法复制到调用站点。
内联属性不能具有支持field

fun main(args: Array<String>) {
    print(x)
}

var i = 10
inline var x: Boolean
    get() = i == 11
    set(x) { x}

We can set inline separately on the get and set methods too.

我们也可以在get和set方法上分别设置内联。

修饰类型参数 (Reified Type Parameters)

The type of a parameter cannot be retrieved in code since it’s erased at runtime. For inline functions though it is possible using Reified.
To retrieve the type of a parameter, we can set a reified modifier against it.
Why does this work?
Inline functions copy the complete function at runtime, hence the type of the parameters is also available provided we’ve set reified against it.

参数的类型无法在代码中检索,因为在运行时已将其删除。 对于内联函数,虽然可以使用Reified。
要检索的参数类型,我们可以设置一个reified反对修改。
为什么这样做?
内联函数会在运行时复制完整的函数,因此只要我们对其设置了具体化,参数的类型也是可用的。

fun main(args: Array<String>) {
    getT<Double>()
}

inline fun <reified T> getT() {
    print(T::class)
}

The following output gets printed:

打印以下输出:

That’s all for kotlin inline functions tutorial, we will look into more Kotlin features in future tutorials.

这就是kotlin内联函数教程的全部内容,我们将在以后的教程中研究更多Kotlin功能。

翻译自: https://www.journaldev.com/19775/kotlin-inline-function-reified

kotlin内联函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值