Lambda表达式
-
为什么需要引入Lambda表达式?
答:为了方便代码块的传递,Lambda表达式是一个可传递的代码块,因为java是面向对象的编程,所以不能直接在将代码块进行传递,需要将所需要的代码块放在一个对象里面,所以这个对象对应的类必须有一个方法包含所需要传递的代码。其他语言可以直接处理代码块不需要用对象;
带参数变量的表达式就被称为Lambda表达式。
-
语法
-
第一个Lambda表达式
(String fiirst,String sencond)->first.length-second.length; //参数 —>表达式
注意:需要严格规定变量的类型,由于java是一种强类型的语言
-
即使没有变量也要写()->表达式
-
如果可以推导出参数的类型可以省略参数的类型
Comparator<String> comp = (first,second)->{}; //此时可以推出是String类型
-
如果只有一个参数且可以推断出该参数的类型,即使是()也可以省略;
-
无需指定Lambda表达式的返回值类型,它会根据上下文推导得到;
-
-
第二个表达式:如果后面的表达式一个式子写不完就写成{}方法体的形式
(String first,String second)-> { //执行的代码 }
-
函数式接口
比如Comparator
lambda表达式与这些接口是兼容的
@FunctionalInterface
注解标注函数式接口functional interface:只有一个抽象方法的接口,需要这种接口的对象的时候,可以通过Lambda表达式来实现;【接口可以有非抽象的方法】
也就是说Lambda表达式就是函数式接口中抽象方法覆写的方法体内容;
函数式接口其实就是指只含有一个抽象方法的接口,其目的就是用来传递代码块也就是Lambda表达式
为有特定用途的Lambda表达式建立特定的函数式接口作为传递表达式
Arrays.sort(word,(first,second)->first.length-second.length) //1.Arrays.sort()底层会接收实现了Comparator<String>的某个类的对象。在对象上调用compare方法执行lambda表达式的方法体
- lambda表达式可以转换为接口【函数式接口才可以使用lambda表达式】java.util.functon中有很多函数式接口
-
保存Lambda表达式变量
Comparator<String> comp = (first,second)->first.length-second.length; //相当于实现了Comparator类型的实例对象,并且该对象还覆写了抽象方法并且方法体为Lambda表达式对应的内容
-
方法引用
Timer timer = new Timer(1000,System.out::println); //实现将System.out中的方法引用到ActionListener函数式接口实现对象的覆写方法中;
实现步骤:
- 指示编译器生成一个函数式接口的实例
- 覆写函数式接口中的抽象方法
- 在方法中引用System.out的println方法作为方法体实现方法引用
语法
对象或类名称::方法名称 //实现方法传递等价于(参数类型 参数名称)->类.方法()
注意:
-
只有当Lambda表达式的体只有一个方法不做其他操作的情况下才能把Lambda表达式重写为方法引用;
-
方法引用中可以使用
this
参数以及super
this::equals //等价于下面 x->this.equals(x)
-
构造器引用
Person::new //等同于以下,参数根据上下文决定重载哪个构造器 ()->new Person()
-
变量作用域
希望能够使得Lambda表达式访问外围变量也就是非Lambda代码块中的变量
Lambda表达式包括三个部分:
- 一个代码块
- 参数
- 自由变量值,指的非参数且不在代码中定义的变量
Lambda表达式的作用域与嵌套它的代码块作用域相同;
public static void repeatMessage(String text,int delay){ ActionListener listener = event-> { System.out.println(text); } new Timer (delay,listener).start; }
lambda表达式会存储自由变量的值,也可以说自由变量被Lambda表达式捕获了。关于代码块和自由变量有一个术语:闭包,在java中Lambda表达式就是闭包(closure).
上述例子中text变量就是自由变量,
注意:
- 在Lambda中只能引用的外部作用域变量不能改变变量。
- 被Lambda表达式引用的变量在外部也是不可改变的。
- Lambda表达式中捕获的变量必须实际上是事实最终变量(这个变量初始化后就不会再为其赋新值。)
-
在Lambda表达式中使用
this
关键字public class Application{ public void test(){ ActionListener listener = event-> { System.out.println(this.toString()); } } }
上述的this指代的是创建这个Lambda表达式的方法的this参数;所以上述的this指的就是Application对应的实例对象中的方法而不是ActionListener。