Lambda表达式,在kotlin中,使用范围非常广。高阶函数、内联函数、委托属性等方式都要基于对lambda的理解。kotlin的lambda与java一脉相承,却不尽相同。
1、lambda表达式概念
lambda表达式在kotlin中是可以理解是一个可以复用的代码块。可以被其他的函数调用。
2、lambda代码书写
一个Lambda表达式把一小段行为进行编码,你能把它 当做值到处传递,它可以被 独立地声明并存储到一个变量中,但是最常见的还是直接声明它并传递给函数,Lambda表达式的语法,->前为 参数,后为 函数体,始终用 花括号包围。
{ a: Int, b: Int -> a + b }
如果,这个lambda表达式作为实参传递的时候,数据类型是可以推导出来的,我们可以进一步的简化
{ a, b -> a + b }
当然lambda表达式也可以写成多行,例如:
{ a: Int, b: Int ->
print("advancedfun")
val x = a + b ;
a - x ;}
3、lambda的作用域
lambda只作用于调用的函数中,并且也可以获得函数的参数,可以改变函数体内lambda表达式之前的局部变量,和函数所在类的成员变量,当然也可以改变所在类对象的成员变量。如下所示:
fun testAdvancedfun(args: Array<String>, c: Int) {
var d = 1;
advancedfun { a: Int, b: Int ->
print("advancedfun")
d++
val x = a + b + c + d;
a - x;
}
print("$d")
}
注:这边有个非常不一样的一点,java在使用lambda的时候,lambda表示的内部类,java只允许使用final的局部变量。但是kotlin是不用的,kotlin很好的规避了这一点,我们看一下java编译的代码:
public static final void testAdvancedfun(@NotNull String[] args, final int c) {
Intrinsics.checkParameterIsNotNull(args, "args");
final IntRef d = new IntRef();
d.element = 1;
advancedfun((Function2)(new Function2() {
// $FF: synthetic method
// $FF: bridge method
public Object invoke(Object var1, Object var2) {
return this.invoke(((Number)var1).intValue(), ((Number)var2).intValue());
}
public final int invoke(int a, int b) {
TestKt.print("advancedfun");
int var10001 = d.element++;
int x = a + b + c + d.element;
return a - x;
}
}));
print(String.valueOf(d.element));
}
他通过一个Final的IntRef做为载体,很好的规避了此问题,当然这也是我们在Java中规避的策略(1、使用成员变量定义 2、使用一个包装类 3、创建单元素的数组)
4、lambda引用的概念
lambda函数是可以赋值和获取引用的,如下:
fun testAdvancedfun2(args: Array<String>, c: Int) {
fun testFun(i: Int, i1: Int) = { a: Int, b: Int -> a * b };// 赋值到函数testFun
var testFunRef = ::testFun; // 获取testFun函数的引用
}
当然,我们也可以把这个函数的引用进行传递,如下
fun advancedfun2(operation: KFunction2<@ParameterName(name = "i") Int, @ParameterName(name = "i1") Int, (Int, Int) -> Int>) {
val result = operation(2, 3)
println("The result is $result")
}
fun testAdvancedfun2(args: Array<String>, c: Int) {
fun testFun(i: Int, i1: Int) = { a: Int, b: Int -> a * b };
var testFunRef = ::testFun;
advancedfun2(testFunRef);
}
也就是说函数的引用类型叫KFunction,有几个参数就是KFunctionX,这其实在java里就是方法的反射。