El uso de Lambda en Kotlin 4. Función en línea en línea

1. Funciones en línea

        Las funciones modificadas con la palabra clave inline se denominan funciones en línea. La modificación en línea es una función de orden superior que utiliza funciones como parámetros. Si modifica una función ordinaria, será una advertencia. El impacto esperado en el rendimiento de la incorporación es insignificante. La incorporación funciona mejor para funciones con parámetros de tipos funcionales, y el impacto de La función ordinaria que se incluye en el rendimiento es insignificante.

2. Los beneficios de utilizar en línea para modificar funciones de orden superior

        Usamos declaraciones de funciones ordinarias y declaraciones de funciones en línea para funciones de orden superior en Kotlin y luego las convertimos a código Java y las comparamos. código kotlin:

class Test {
    //不使用inline 修饰的高阶函数
    fun test(f: () -> Unit) {
        f()
    }
    //使用inline 修饰的高阶函数
    inline fun testInline(f: () -> Unit) {
        f()
    }
    fun call() {
        test { print("test") }
        testInline { print("testInline") }
    }
}

código java:

public final class Test {
   public final void test(@NotNull Function0 f) {
      Intrinsics.checkNotNullParameter(f, "f");
      f.invoke();
   }

   public final void testInline(@NotNull Function0 f) {
      int $i$f$testInline = 0;
      Intrinsics.checkNotNullParameter(f, "f");
      f.invoke();
   }

   public final void call() {
      this.test((Function0)null.INSTANCE);
      int $i$f$testInline = false;
      int var3 = false;
      String var4 = "testInline";
      boolean var5 = false;
      System.out.print(var4);
   }
}

        Se puede ver en la llamada que esta función se llama directamente cuando se llama a una función no en línea, y se crea la clase anónima Function0 para llamar a la función Lambda. Las funciones en línea copian el cuerpo de la función en lugar de crear una clase anónima, pero incrustan directamente el Lambdacuerpo de implementación de la función.

        Cuando una función de orden superior no está Inlinedecorada, llamar a esta función hará referencia directa a esta función y se creará una clase anónima para implementar la llamada de este parámetro de función. Esto tiene dos partes de sobrecarga. Llamar directamente a esta función creará una función adicional marco de pila y empujarlo en la pila. La operación pop (una llamada a función es un proceso de empujar y sacar un marco de pila) y la creación de clases anónimas también consumirán rendimiento. El uso de Inline para modificar funciones de orden superior mejorará el rendimiento.

         Al llamar a una función en línea, según lo anterior, ya sabemos que la inserción incrustará Lambdael cuerpo de la función de parámetro directamente, y la inserción puede conducir a un aumento en el código generado; sin embargo, si lo usamos correctamente (es decir , evitamos la inserción demasiado grande). funciones ), se han realizado mejoras en el rendimiento, especialmente en llamadas "megamórficas" en bucles.

3. Deshabilitar en línea no en línea

        Si desea incluir solo una parte de los parámetros de la expresión lambda pasados ​​a la función en línea, puede usar  noinline modificadores para marcar los parámetros de la función que no desea incluir en línea:

inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) { //…… }

        Las expresiones lambda en línea solo llamar dentro de funciones en línea o pasarse como argumentos a funciones en línea . Se requiere ninguna modificación en línea cuando se pasa como parámetro de una función no en línea o se almacena en un campo.

inline fun testInline(f1: () -> Unit,  f: () -> Unit) {
    f1.invoke()
    val a = f//会提示错误,内联Lambad 不能参数赋值
    testInlineInner(f) //会提示错误,内联Lambad 不能作为普通函数参数进行传递
}

fun testInlineInner(f: () -> Unit) {
    f()
}
inline fun testInline(f1: () -> Unit,  noinline f: () -> Unit) {
    f1.invoke()
    val a = f//可以
    testInlineInner(f) //可以
}

4. Utilice return (retorno no local) en expresiones lambda en funciones en línea

        En Kotlin, solo podemos salir utilizando un retorno normal y no calificado de una función con nombre o anónima. Para salir de una expresión lambda, debemos usar una etiqueta. El uso de bare dentro de una expresión lambda está prohibido  returnporque una expresión lambda no puede hacer que la función que la contiene regrese.

fun testInlineInner(f: () -> Unit) {
    f()
}
testInlineInner {
        return//'return' is not allowed here
    }

Pero si la función pasada por la expresión lambda está en línea, el retorno también puede estar en línea, por lo que está permitido. Este tipo de retorno (ubicado en la expresión lambda, pero saliendo de la función que lo contiene) se denomina retorno no local .

inline fun testInlineInner(f: () -> Unit) {
    f()
}

fun main(args: Array<String>) {
    testInlineInner {
        return// 可以,退出main函数
    }
}

5. en línea cruzada

        Cuando la inserción Lambdano se llama directamente en el cuerpo de la función, sino en una función anidada u otro entorno de ejecución, debe declararse comocrossinline。

inline fun f(crossinline body: () -> Unit) {
   val f = Runnable { body() }
}

六、Parámetros de tipo Reificado

        reified es la palabra clave de Kotlin sobre genéricos, para que los genéricos no se borre. Si necesita usar reified para modificar el tipo genérico en un método genérico, debe usar Inline para modificar el método genérico, porque la función Inline puede especificar el tipo genérico El tipo de tipo no se borra, porque la función en línea incrustará el código de bytes en el lugar donde se llama durante la compilación, por lo que el compilador sabrá el tipo específico correspondiente al genérico. El uso de reificado e Inline es adecuado para métodos genéricos, y el método Es necesario juzgar el tipo genérico en el cuerpo. ​​​​​​​

inline fun <reified T> Bundle.plus(key: String, value: T) {
    when (value) {
        is String -> putString(key, value)
        is Long -> putLong(key, value)
        is Int -> putInt(key, value)
    }
}

7. Atributos en línea

inlineTambién puede modificar setel getmétodo y puede modificar directamente las propiedades para que ambos descriptores de acceso estén marcados comoinline。

class Amount(var amount: Long) {
    private val isEmpty: Boolean
        inline get() {
            return amount <= 0
        }

    private val isEmptyNoInline: Boolean
        get() {
            return amount <= 0
        }

    fun test(){
       val amount = Amount(10)
        val isEmpty = amount.isEmpty
        val isEmptyNoInline = amount.isEmptyNoInline
    }
    //转化为Java代码
    public final void test() { 
      Amount amount = new Amount(10L);
      int $i$f$isEmpty = false;
      boolean isEmpty = amount.getAmount() <= 0L; //代码嵌入
      boolean isEmptyNoInline = amount.isEmptyNoInline(); //非嵌入
   }
}

1. Introducción al uso de expresiones Lambda en la API funcional de la colección.

2. Tipos de funciones y creación de instancias

3. Conversión SAM (Conversiones de método abstracto único)

4. Función en línea en línea

Supongo que te gusta

Origin blog.csdn.net/old_land/article/details/119612708
Recomendado
Clasificación