美文网首页我的Python自学之路Android开发
inline、noinline和crossinline区别

inline、noinline和crossinline区别

作者: 戎码虫 | 来源:发表于2022-02-10 09:11 被阅读0次

    内联函数

    内联函数消除了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区别

        本文链接:https://www.haomeiwen.com/subject/dfjgkrtx.html