在 Android 开发中 Lambda 表达式
的越来越受到青睐,特别是在 Kotlin
中极大的方便了编程,被大家广泛的接受、使用,那么之前,了解 Lambda 的相关内容就显得十分必要了。
1、Lambda 表达式语法
Lambda 表达式:(argment) -> (body)
Lambda 表达式由 参数列表
、箭头(->)
、函数体
三部分组成。其中函数体可以是 表达式 也可以是 语句块。
- 表达式:执行表达式后返回结果
- 语句块:依次执行语句块中语句
举例:
(int a,int b)-> {
sout("执行语句")
return a+b;
}
1. 在 Lambda 表达式中,如果根据上下文可以推断出参数的数据类型,那么参数类型是可以省略的。
(a,b) -> {
sout("执行语句")
return a+b;
}
2. 如果 只有一个参数
,同时参数类型可以根据上下文推断出来,那么此时 ()
可以被省略。
a ->{
sout("执行语句")
return a * 2;
}
3. 如果代码块里只有一行代码,那么可以省略 {}
。
a -> return a * 2;
此时 return 也就没有什么意义了,可以这样写:
a -> a * 2;
4. 但是当没有参数的时候,()
必须存在。
() -> a * 2;
2、函数式接口(Functional interfaces)
使用 Lambda 表达式
就不得不知道什么是 函数式接口,因为 Lambda 表达式
无非是 函数式接口 的一种表示方式。
函数式接口是只有一个 抽象方法 的接口
,希望能够记住定义,很重要。
举个例子:View#OnClickListener
就是一个函数接口
public interface OnClickListener {
void onClick(View var1);
}
而 TextWatcher
就不是一个函数接口
public interface TextWatcher extends NoCopySpan {
void beforeTextChanged(CharSequence var1, int var2, int var3, int var4);
void onTextChanged(CharSequence var1, int var2, int var3, int var4);
void afterTextChanged(Editable var1);
}
所以 OnClickListener
可以使用 Lambda 表达式
表示,而 TextWatcher
不可以使用 Lambda 表达式
表示。
在 Java8 中接口可以有非抽象方法,具体可以参见
文章参考
链接中相关表述。
3、Lambda 表达式的目标类型以及匹配
Lambda 表达式
可以当做一个 Object
,但是它有自己的类型名称 – 目标类型 (Target Type ),Lambda 表达式
的目标类型是 函数接口
,我们不能把 Lambda 表达式
赋值给 Object
,只有在转型函数接口后才可以被当做 Object
使用。
//可以用一个Lambda表达式为一个函数接口赋值
Runnable r1 = () -> {System.out.println("Hello Lambda!");};
//然后再赋值给一个Object
Object obj1 = r1;
//必须显式的转型成一个函数接口才可以
Object obj3 = (Runnable) () -> { System.out.println("Hello Lambda!"); };
//必须先转型
System.out.println( (Runnable)() -> {} ); // 正确
//不能这样干 ERROR! Object is not a functional interface!
Object obj2 = () -> {System.out.println("Hello Lambda!");};
//Lambda表达式只有在转型成一个函数接口后才能被当做Object使用,所以下面这句也不能编译
System.out.println( () -> {} ); //错误! 目标类型不明确,println方法可以接受任何类型的参数,而() -> {}能匹配上很多函数接口
注意
以上表述中具体 Lambda 表达式
写法只适用于 Java,Kotlin 有其自己的写法。