inline、noinline和crossinline区别

内联函数

内联函数消除了Lambda表达式所带来的运行时内存开销,简化编码方式

正常函数
fun main() {
    val num1 = 1
    val num2 = 10
    val numberAdd = numberAdd(num1, num2)
    println(numberAdd)
}

fun numberAdd(num1: Int, num2: Int): Int {
    return num1 + num2
}

decompile后的Java代码

public final class MainKt {
   public static final void main() {
      int num1 = 1;
      int num2 = 10;
      int numberAdd = numberAdd(num1, num2);
      boolean var3 = false;
      System.out.println(numberAdd);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final int numberAdd(int num1, int num2) {
      return num1 + num2;
   }
}

正常函数传参返回结果,方法实例正常出入栈

inline

使用inline修饰的函数

fun main() {
    val num1 = 1
    val num2 = 10
    val numberAdd = numberAdd(num1, num2)
    println(numberAdd)
}

inline fun numberAdd(num1: Int, num2: Int): Int {
    return num1 + num2
}

decompile后的Java代码

public final class MainKt {
   public static final void main() {
      int num1 = 1;
      int num2 = 10;
      int $i$f$numberAdd = false;
      int numberAdd = num1 + num2;
      $i$f$numberAdd = false;
      System.out.println(numberAdd);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final int numberAdd(int num1, int num2) {
      int $i$f$numberAdd = 0;
      return num1 + num2;
   }
}

用inline修饰后相当于直接把函数里面的代码拷贝过去了

fun main() {
    val numberAdd = num1 + num2
    println(numberAdd)
}

noinline

为什么会存在noinline关键词,先看一段代码

fun main() {
    var num1 = 1
    val num2 = 10
//    val numberAdd = numberAdd(num1, num2)

    val numberAdd = numberAdd({
        num1 * 10
    }, { num2 * 10 })
    println(numberAdd)
}

inline fun numberAdd(block: () -> Int, block2: () -> Int): Int {
    return block() + block2()
}

decompile后的Java代码

public final class MainKt {
   public static final void main() {
      int num1 = 1;
      int num2 = 10;
      int $i$f$numberAdd = false;
      int var4 = false;
      int var5 = num1 * 10;
      var4 = false;
      int var6 = num2 * 10;
      int numberAdd = var5 + var6;
      $i$f$numberAdd = false;
      System.out.println(numberAdd);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final int numberAdd(@NotNull Function0 block, @NotNull Function0 block2) {
      int $i$f$numberAdd = 0;
      Intrinsics.checkParameterIsNotNull(block, "block");
      Intrinsics.checkParameterIsNotNull(block2, "block2");
      return ((Number)block.invoke()).intValue() + ((Number)block2.invoke()).intValue();
   }
}

当我们不需要其中一个函数内联时,可以采用noinline修饰,此时第二个函数参数就不会内联进去

fun main() {
    var num1 = 1
    val num2 = 10
//    val numberAdd = numberAdd(num1, num2)

    val numberAdd = numberAdd({
        num1 * 10
    }, { num2 * 10 })
    println(numberAdd)
}

inline fun numberAdd(block: () -> Int,noinline block2: () -> Int): Int {
    return block() + block2()
}
public final class MainKt {
   public static final void main() {
      int num1 = 1;
      final int num2 = 10;
      Function0 block2$iv = (Function0)(new Function0() {
         // $FF: synthetic method
         // $FF: bridge method
         public Object invoke() {
            return this.invoke();
         }

         public final int invoke() {
            return num2 * 10;
         }
      });
      int $i$f$numberAdd = false;
      int var5 = false;
      int numberAdd = num1 * 10 + ((Number)block2$iv.invoke()).intValue();
      boolean var6 = false;
      System.out.println(numberAdd);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final int numberAdd(@NotNull Function0 block, @NotNull Function0 block2) {
      int $i$f$numberAdd = 0;
      Intrinsics.checkParameterIsNotNull(block, "block");
      Intrinsics.checkParameterIsNotNull(block2, "block2");
      return ((Number)block.invoke()).intValue() + ((Number)block2.invoke()).intValue();
   }
}
crossinline

先看一段代码

fun main() {
    println("开始")
    printOddNum(10) {
        println("函数开始")
        if (it % 2 == 0) return
        println("我是奇数$it")
    }
    println("后面还有代码要执行呢")
}


inline fun printOddNum(i: Int, block: (Int) -> Unit) {
    block(i)
}

打印结果

开始
函数开始

这段代码函数的功能是打印奇数,当遇到偶数的时候,调用return,使函数结束,但是同时也导致外部函数也结束了,这样的话局部函数就影响了整个外部函数逻辑

如果我们不想局部函数影响整个函数的逻辑,我们就在方法上添加crossinline关键字修饰
inline fun printOddNum(i: Int, crossinline block: (Int) -> Unit) {
    block(i)
}

这个时候调用函数,编译器就会提示我们,return@函数名 进行局部返回


报错信息
fun main() {
    println("开始")
    printOddNum(10) {
        println("函数开始")
        if (it % 2 == 0) return@printOddNum
        println("我是奇数$it")
    }
    println("后面还有代码要执行呢")
}


inline fun printOddNum(i: Int, crossinline block: (Int) -> Unit) {
    block(i)
}

打印结果

开始
函数开始
后面还有代码要执行呢

这个时候就正常了

你可能感兴趣的:(inline、noinline和crossinline区别)