kotlin语法复习--->局部返回,inline,noinline和crossinline

kotlin语法复习--->局部返回,inline,noinline和crossinline

  1. inline关键字

    inline关键字是作用:

    • 在函数上的一个关键字,其作用就是在class文件中,kotlin的函数体代码会直接放在调用的位置

    • 另外就是,当函数类型参数含有函数类型参数时,添加inline关键字会提高程序的性能,但是,该函数参数不能作用一般的参数进行参数调用。

      fun test() {
          hasInlineFunc {
              println("hasInlineFunc")
          }
          noInlineFunc {
              println("noInlineFunc")
          }
      }
      
      inline fun hasInlineFunc(action: () -> Unit) {
          action()
      }
      
      fun noInlineFunc(action: () -> Unit) {
          action()
      }
      

      相应的字节码文件:

      public static final void test() {
            // hasInlineFunc: 函数体内容
            String var2 = "hasInlineFunc";
            System.out.println(var2);
            // noInlineFunc: 函数调用
            noInlineFunc((Function0)null.INSTANCE);
         }
      
         public static final void hasInlineFunc(@NotNull Function0 action) {
            Intrinsics.checkNotNullParameter(action, "action");
            action.invoke();
         }
      
         public static final void noInlineFunc(@NotNull Function0 action) {
            Intrinsics.checkNotNullParameter(action, "action");
            action.invoke();
         }
      

      接下来就是解释上面第二句的意思,由于inline修饰函数会直接将函数体内容放在相应调用的位置,所以其函数类型参数就不能作为一个引用来进行使用。

      fun func(action: () -> Unit) {
      
      }
      
      inline fun hasInlineFunc(action: () -> Unit) {
          action()
          func(action) // 在这里会出现编译错误(可以在参数action前面添加noinline,这个在后面说)
      }
      
  2. noline

    上面也已经说了,inline修饰的函数,其函数类型参数不能够作用一般的参数进行调用,那么noinline关键字就是解决这个问题。还是接着上面的代码案例

    fun func(action: () -> Unit) {
    
    }
    
    inline fun hasInlineFunc(action: () -> Unit) {
        action()
        func(action) // 在这里会出现编译错误(可以在参数action前面添加noinline,这个在后面说)
    }
    
    // 解决方式一: 添加 noinline 关键字
    inline fun hasInlineFunc(noinline action: () -> Unit) { // 这里会出现黄色的警告(可以在添加一个没有noinline关键字修饰的函数类型参数)
        action()
        func(action) 
    }
    
    // 解决方式二: 删除inline 关键字
    fun hasInlineFunc(action: () -> Unit) {
        action()
        func(action) 
    }
    
  3. crossinline

    再介绍crossinline之前需要提一下局部返回和非局部返回。

    局部返回:

    fun test(): Int{
        func {
            if (it == 1) {
                return@func // 局部返回: 只是当前的函数体结束,该函数体作用域是在(func函数中的)
                // return 1 非局部返回,test方法直接结束,并返回1
            }
            println("action$it 执行中")
        }
        return 1
    }
    
    fun func(action: (Int) -> Unit) {
        println("func 开始执行")
        for (i in 0..2) {
            println("action$i 开始执行")
            action(i)
            println("action$i 执行结束")
        }
        println("func 执行结束")
    }
    // 输出结果
    func 开始执行
    action0 开始执行
    action0 执行中
    action0 执行结束
    // action1未执行,因为存在局部返回
    action1 开始执行
    action1 执行结束
    
    action2 开始执行
    action2 执行中
    action2 执行结束
    func 执行结束
    
  • inline修饰的函数可以进行非局部返回(也就是可以使用return),没有inline修饰的函数只能进行局部返回(return@局部函数域名)

    inline fun hasInlineFunc(action: () -> Unit) {// 添不添加crossinline都一样,添加后可以提示我们,action的lambda中不要出现return,因为该函数有可能会在其他的lambda中进行调用
        action()
    }
    
    fun noInlineFunc(action: () -> Unit) {
        action()
    }
    
    fun test(): Int{
        // 可以进行函数域自定义命名: 名字@
        noInlineFunc func1@{ // 不能进行非局部返回
            println("noInlineFunc")
            // 但是hasInlineFunc函数是inline函数,可以进行非局部返回,也就是return
            // 在下面使用return还是会出错, 这里就会出现矛盾,所以为了给我们程序员提示,在hasInlineFunc的参数action前面添加crossinline就是告诉我们action的lambda中不能出现return语句,只能进行局部返回
            hasInlineFunc func2@{
    			// return 2 还是编译出错
            }
    		// return 2 编译出错
        }
        return 1
    }
    

posted @ 2021-10-03 18:15  SowHappy  阅读(266)  评论(0)    收藏  举报