整理了下以前的本地笔记,鉴于之前部分笔记丢失,觉得还是上传到博客中比较稳妥。
1.lambda表达式介绍:
匿名方法。
使JAVA可以写出更简洁,更灵活的代码。作为一种更紧凑的代码风格,使java的语言表达能力得到了提升。
//匿名内部类:
mLambdaButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Hello Word", Toast.LENGTH_SHORT).show();
}
});
//lambda:
mLambdaButton.setOnClickListener(v -> {Toast.makeText(this, "Hello World", Toast.LENGTH_SHORT).show();});
引入了新的语法元素和操作符:”->“箭头操作符(lambda操作符)。
2.lambda表达式语法规则:
lambda表达式的语法由参数列表、箭头符号->和函数体组成。函数体既可以是一个表达式,也可以是一个语句块:
(x,y)-> System.out.println(“Hello Wold!!”)
表达式函数体消除了return关键字,使得语法更加简洁。
3. lambda表达式使用与匿名内部类使用的比较:
区别于匿名内部类几个”缺点“:
①语法过于冗余;
②匿名类中的this和变量名容易使人产生误解
③无法捕获非final声明的局部变量(这个java8之后匿名内部类也可以进行捕获了, 但其实无论lambda还是java8都只能捕获具有final性质的局部变量,这个仅仅是让你省略写"final"这个关键字)
lambda需要函数式接口的支持
函数式接口:只有一个方法的接口。
4. 目标类型(Target typing)
作为替代匿名内部类的lambda表达式,同样也应该像匿名内部类一样有自己的类型
例如,下面代码中的lambda表达式类型是OnClickListener:
OnClickListener l = (View v) -> Log.d(“tag”,”yapple”);
这就意味着同样的lambda表达式在不同环境中可以拥有不同的类型:
public class myClass {
public static void function1(CallBack1 call1) {
Log.i("function1", call1.fun1());
}
public static void function2(CallBack2 call2) {
Log.i("function2", call2.fun1());
}
/**
* 在这个例子中两个 “ () -> "yapple" ” lambda表达式表示的类型分别是CallBack1和CallBack2
**/
public static void main(String[] args) {
function1(() -> "yapple");
function2(() -> "yapple");
}
}
第一个lambda表达式() -> "apple"是 CallBack1 的实例,而第二个lambda表达式则是CallBack2 的实例。
编译器负责推导lambda表达式的类型。它利用lambda表达式所在上下文所期待的类型进行推导,这个被期待的类型被称为目标类型。lambda表达式只能出现在目标类型为函数式接口的上下文中。
当然,lambda表达式对目标类型也是有要求的。编译器会检查lambda表达式的类型和目标类型的方法签名(method signature)是否一致。当且仅当下面所有条件均满足时,lambda表达式才可以被赋给目标类型T:①T是一个函数式接口 (函数式接口:只有一个方法的接口)
②lambda表达式的参数和T的方法参数在数量和类型上一一对应 (非重载)
③lambda表达式的返回值和T的方法返回值相兼容(Compatible) (返回值可是继承关系)
④lambda表达式内所抛出的异常和T的方法throws类型相兼容 (同上,抛出异常也是可继承关系)
由于目标类型(函数式接口)已经“知道”lambda表达式的形式参数(Formal parameter)类型,所以我们没有必要把已知类型再重复一遍。也就是说,lambda表达式的参数类型可以从目标类型中得出:
OnClickListener l = (v) -> Log.d(“tag”,”this is lambda”);
在上面的例子里,编译器可以推导出v和的类型是View。此外,当lambda的参数只有一个而且它的类型可以被推导得知时,该参数列表外面的括号可以被省略:
button.addOnClickListener(v -> Log.d(“tag”,”this is lambda”));
lambda表达式并不是第一个拥有上下文相关类型的Java表达式:泛型方法调用和“菱形”构造器调用也通过目标类型来进行类型推导:
List<String> ls = Collections.emptyList();
List<Integer> li = Collections.emptyList();
Map<String, Integer> m1 = new HashMap<>();
Map<Integer, String> m2 = new HashMap<>();
附:
java中lambda表达式语法规则例子:
语法格式一:无参数,无返回值:
() - > System.out.println(“Hello Lambda”)
语法格式二:有一个参数,且无返回值(只有一个参数时括号可以省略):
省略前:(x) - > System.out.println(“Hello Lambda”)
省略后: x - > System.out.println(“Hello Lambda”)
语法格式三:有两个以上的参数,有返回值,并且Lambda执行语句中有多条语句:
(x,y) - > { int sum = x + y;
System.out.println(“x 与 y 的和为: ” + sum);
return sum; }
语法格式四:有返回值,但执行体只有一条语句,
(x,y) - > x + y 大括号和return都可以省略。
语法格式五: 双冒号 :: ,是对 () -> { } 方式的进一步简化。看下例对比
mButton.setOnClickListener( v -> onButtonClick( v ) );
mButton.setOnClickListener(this::onButtonClick);
网友评论