Lambda表达式是Java8的重要更新。 Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(之中接口被称为函数式接口)的实例。
如可将
pa.process(target,new Command(){ //匿名内部类
public void process(int []target){
int sum=0;
for(int tmp:target){
sum+=tmp;
}
System.out.println("数组元素的总和是:"+sum);
}
});
改写为
pa.process(target,(int []target)->{ //lambda表达式
int sum=0;
for(int tmp:target){
sum+=tmp;
}
System.out.println("数组元素的总和是:"+sum);
});
比较可知,lambda表示省略了要被继承的父类名,或要实现的接口名,直接给出要重写的方法的形参列表,连函数名也都省略,只保留函数内部的语句。也不需要给出要被重写的函数的返回值类型。
lambda表达式实际上会被当成一个“任意类型”的对象。到底需要当成何种类型的对象,取决于运行环境的需要。
Lambda表达式与函数式接口:
函数式接口代表只包含一个抽象方法的接口。
lambda表达式有两个限制:①目标类型必须是明确的函数式接口。②只能为函数式接口创建对象。
如
Object obj=()->{};//方法会报错,因为目标obj不是函数式接口
Object obj=(Runnable)()->{};//成功运行,对lambda表达式进行强制类型转换,Runnable是函数式接口
为了保证lambda表达式的目标类型是一个明确的函数式接口,有如下三种常见方式:
①将lambda表达式赋值给函数式接口类型的变量。
②将lambda表达式作为函数式接口类型的参数传给某法方法。
使用函数式接口都lambda表达式进行强制类型转换
方法引用和构造器引用:
1.引用类方法:
Converter converter1=Integer::valueOf;
2.引用特定对象的实例方法
Converter converter2="fkit.org"::indexOf;
3.引用某类对象的实例方法
MyTest mt=(a,b,c)->a.substring(b,c); //原
MyTest mt=String::substring; //新
4.引用构造器
YourTest yt=(String a)->new JFranme(a); //原
YourTest yt=JFranme::new; //新
lambda表达式和匿名内部类的联系和区别:
相同点:
①都可以直接访问“effectively final”的局部变量,以及外部类的成员变量。
②两者创建的对象,都可以直接调用接口中继承的默认方法
不同点:
①匿名内部类可以生成所有的抽象方法,但是lambda表达式只能为函数式接口(只有一个抽象方法)创建实例。
②匿名内部类可以为抽象量、普通类创建实例;但是lambda表达式只能为函数式接口。
③匿名内部类实现的抽象方法的内部允许调用接口中定义的默认方法;但是lambda表达式的代码块中不允许调用接口中定义的默认方法。
使用lambda表达式调用Arrays的类方法:
Arrays类的有些方法需要Comparator、xxxOperator。xxxFunction等接口的实例,这些接口都是函数式接口,因此可以使用lambda表达式来调用Arrays的方法。