Kotlin学习(二)之--从函数 -->匿名函数 -->lambda功能特性(结合反编译 对比Java)

小小知识点:Unit相当于void,但Unit是一个类型,而void是一个关键字,表示不用返回值

一. 函数
1.1定义:
fun + 函数名(参数 :参数类型) :返回值类型{}
例:

fun method1( a : Int, b : Int) : String{
    
    
    return "a + b"
}

不加权限修饰符默认是public
看一下反编译成Java代码的效果:

   @NotNull
   public static final String method1(int a, int b) {
    
    
      return "a + b";
   }

注意:不能在不同的kt文件里定义相同的函数,可以重载,即参数个数及类型或返回值不一样

1.2 函数的默认参数:

fun method1( a : Int, b : Int = 47) : String{
    
    
    return "a + b"
}

这样在调用函数的时候可以选择赋一个值,也可以选择赋俩个值
如:

fun main() {
    
    
      println(method1(40));
      println(method1(20,20))
}
fun method1( a : Int, b : Int = 47) : Int{
    
    
    return a + b
}

运行结果:
在这里插入图片描述
注意:默认参数得在最后一个,否则在赋值的时候可能报错
如:
在这里插入图片描述
此时解决方法有俩种:

  1. 调用方法的时候给a也一块赋值
  2. 利用具名参数这一性质赋值
    println(method1(10,40))//将a也一并赋值了
    println(method1(b = 20))//具名参数赋值给没有默认值的参数

二. 匿名函数
1.1第一种匿名函数写法(必须指明返回值的类型)
var/val 函数名 :(参数类型) -> 返回值类型{参数名 ->
具体函数内容
}

     //声明匿名函数,()为输入的参数, -> 后面为输出的内容,就是返回值
    var method2 : () -> Unit //
    method2 = {
    
    
        print("我是方法2")
    } //method2的{}里面就是匿名函数 
    method2() //调用匿名函数

也可以像下面一样:

    var method3 : (Int,Int,Int) -> String = {
    
     a, b, c ->
        var d = a + b + c
        "我是方法3"
    }
    println(method3(1,2,3))
    //输出:我是方法3

说明:a, b, c就是参数名称, 返回值默认是最后一行

1.2 第二种匿名函数写法(利用出色的类推到机制,因此不用指明返回值类型)
写法如下:
var/val 函数名 = {参数名:参数类型 ->
函数具体逻辑
}

    var method4 = {
    
     a : Int, b : Int ->
        "我是方法四"
    }
    println(method4(1,2))
    //输出:我是方法四

好处 ->后面不用强调返回类型,可以返回任意类型值
又如:

    var method4 = {
    
    a: Int, b: Int ->
        var c = "我是方法四"
        1
    }
    println(method4(1,2))
    //输出:1
    var method4 = {
    
    a: Int, b: Int ->
        var c = "我是方法四"
        true
    }
    println(method4(1,2))
    //输出:true

说明 : 匿名函数可以省去return,返回值是最后一行代码
三. it关键字的使用

   var method5 :(String) -> String = {
    
    
          "$it"
    }
    println(method5("我是方法五"))
    //输出:我是方法五

当匿名函数的参数只有一个的时候,it 就是它的参数名称

四. lambda(浅谈,后期再详细写一篇关于lambda的文章)
其实上述的匿名函数就是lambda,关于lambda的特性,美妙之处之后细谈

五.参数是函数的 函数(类比Java,参数是接口)

    var method6 : (Int,Int,(Int,Int)->Unit) -> Unit = {
    
    a,b,add->
        add(a,b);
    }
    method6(10,10){
    
     a : Int, b : Int ->
        a + b
        println("$a + $b = ${
      
      a+b}")
    }
  //运行结果:10 + 10 = 20

说明:类比Java:( Int, Int ) -> Unit 相当于传入了一个接口,而这个接口里有一个方法

 void  add(int a, int b) {
    
     
   打印a + b的值
}

六. 内联函数的声明inline
当函数的参数有lambda表达式时,需要将该函数声明成内联函数,可以降低损耗
对于函数:

fun method1( a : Int = 10, b : Int, add : (Int, Int)->Int) : Int{
    
    
    return add(a,b)
}

1.1未声明未内联函数时:反编译的结果:

   public static final int method1(int a, int b, @NotNull Function2 add) {
    
    
      Intrinsics.checkNotNullParameter(add, "add");
      return ((Number)add.invoke(a, b)).intValue();
   }

   // $FF: synthetic method
   public static int method1$default(int var0, int var1, Function2 var2, int var3, Object var4) {
    
    
      if ((var3 & 1) != 0) {
    
    
         var0 = 10;
      }

      return method1(var0, var1, var2);
   }

缺点:在反编译成Java代码之后会多出一些对象来满足lambda表达式的执行,性能损耗严重
1.2声明了 内联函数后

inline fun method1( a : Int = 10, b : Int, add : (Int, Int)->Int) : Int{
    
    
    return add(a,b)
}

来看一下反编译的结果:

   public static final int method1(int a, int b, @NotNull Function2 add) {
    
    
      int $i$f$method1 = 0;
      Intrinsics.checkNotNullParameter(add, "add");
      return ((Number)add.invoke(a, b)).intValue();
   }

   // $FF: synthetic method
   public static int method1$default(int a, int b, Function2 add, int var3, Object var4) {
    
    
      if ((var3 & 1) != 0) {
    
    
         a = 10;
      }

      int $i$f$method1 = false;
      Intrinsics.checkNotNullParameter(add, "add");
      return ((Number)add.invoke(a, b)).intValue();
   }

。。。尴尬了一波,我这边写的测试案例并不能很好的展示inline的优点,早晚还会再写一个例子展现一下内联的好处

七.函数引用

fun method7( a : Int, b : Int) : Unit{
    
    
    println("$a + $b = ${
      
       a + b}")
}
    var method6 : (Int,Int,(Int,Int)->Unit) -> Unit = {
    
    a,b,add->
        add(a,b);
    }
    method6(5,5,::method7)//调用method6,传入了method7
    //输出: 5 + 5 = 10

综上:在闯入一个函数类型作为参数时,要使用 :: 符号将一个函数变成函数对象

    var oj = ::method7
    var oj2 = oj;
    method6(20,20,oj2)
    //效果与上面一样

八.函数作为返回值类型的函数
1.1具名函数

fun method9(a: Int,b: Int) : Int{
    
    
    return a + b
}
fun method8 (a:Int,b:Int) : (Int,Int) -> Int {
    
    
//    return {c:Int,d:Int ->
//        a + b
//    }
    return ::method9
}
    var resultMethod = method8(10,15)
    println(resultMethod(10,15))
    //调用method8,返回一个函数

1.2匿名函数

fun method9(a: Int) : Int{
    
    
    return a
}
    var method12 : (Int) -> (Int)->Int = {
    
    
        var method13:(Int)->Int = {
    
     c->
            10
    }
        ::method9
    }

返回值为函数的匿名函数 返回值必须是一个具名函数,否则报编译错误
例如:
在这里插入图片描述

=

猜你喜欢

转载自blog.csdn.net/XJ200012/article/details/122501519