Использование Lambda в Kotlin 4. Встроенная функция встроена

1. Встроенные функции

        Функции, измененные с помощью ключевого слова inline, называются встроенными функциями. Встроенная модификация — это функция более высокого порядка, которая использует функции в качестве параметров. Если вы измените обычную функцию, это будет предупреждение. Ожидаемое влияние на производительность от встраивания незначительное. Встраивание лучше всего работает для функций с параметрами функциональных типов, а влияние производительность обычной функции встраивания незначительна.

2. Преимущества использования встроенных функций для изменения функций высшего порядка

        Мы используем обычные объявления функций и встроенные объявления функций для функций высокого порядка в Kotlin, а затем преобразуем их в код Java и сравниваем. котлин-код:

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

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);
   }
}

        В вызове видно, что эта функция вызывается напрямую при вызове невстроенной функции, а для вызова функции Lambda создается анонимный класс Function0. Встроенные функции копируют тело функции вместо создания анонимного класса, а непосредственно встраивают Lambdaтело реализации функции.

        Если функция более высокого порядка не Inlineдекорирована, вызов этой функции будет напрямую ссылаться на эту функцию, и будет создан анонимный класс для реализации вызова этого параметра функции. Это имеет две части накладных расходов. Непосредственный вызов этой функции создаст дополнительный Операция извлечения (вызов функции — это процесс помещения и извлечения кадра стека) и создание анонимных классов также потребляют производительность. Использование Inline для изменения функций высшего порядка улучшит производительность.

         При вызове встроенной функции, исходя из вышеизложенного, мы уже знаем, что встраивание встроит Lambdaтело функции параметра напрямую, а встраивание может привести к увеличению генерируемого кода; однако, если мы используем его правильно (то есть избегаем встраивания слишком большого размера функции ), производительность будет Улучшена, особенно при «мегаморфных» вызовах в циклах.

3. Отключить встроенный noinline

        Если вы хотите встроить только часть параметров лямбда-выражения, переданных встроенной функции, вы можете использовать  noinline модификаторы, чтобы отметить параметры функции, которые вы не хотите встраивать:

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

        Встраиваемые лямбда-выражения можно вызывать только внутри встроенных функций или передавать в качестве аргументов встраиваемым функциям . Никакая строковая модификация не требуется, если она передается в качестве параметра невстроенной функции или сохраняется в поле.

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. Используйте return (нелокальный возврат) в лямбда-выражениях во встроенных функциях.

        В Kotlin мы можем выйти только с помощью обычного, неквалифицированного возврата из именованной или анонимной функции. Чтобы выйти из лямбда-выражения, мы должны использовать метку. Использование bare внутри лямбда-выражения запрещено,  returnпоскольку лямбда-выражение не может вызвать возврат функции, содержащей его.

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

Но если функция, передаваемая лямбда-выражением, является встроенной, возврат также может быть встроен, поэтому это разрешено.Такой тип возврата (находится в лямбда-выражении, но выходит из содержащей его функции) называется нелокальным возвратом .

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

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

5. кросс-лайн

        Если встраивание Lambdaне вызывается непосредственно в теле функции, а вызывается во вложенной функции или другой среде выполнения, его необходимо объявить какcrossinline。

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

六、Параметры типа Reified

        reified — это ключевое слово Kotlin, касающееся дженериков, чтобы дженерики не удалялись. Если вам нужно использовать reified для изменения универсального типа в универсальном методе, вам нужно использовать Inline для изменения универсального метода, поскольку функция Inline может указать универсальный тип Тип типа не стирается, поскольку встроенная функция встроит байт-код в то место, где она вызывается во время компиляции, поэтому компилятор будет знать конкретный тип, соответствующий обобщенному.Использование reified и Inline подходит для обобщенных методов, и Метод. Необходимо судить о родовом типе организма. ​​​​​​

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. Встроенные атрибуты

inlineВы также можете изменить setметод getи напрямую изменить свойства, чтобы оба метода доступа были помечены какinline。

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. Введение в использование лямбда-выражений в функциональном API коллекции.

2. Типы функций и создание экземпляров

3. Преобразование SAM (преобразование одного абстрактного метода)

4. Встроенная

рекомендация

отblog.csdn.net/old_land/article/details/119612708