Java8新增的Lambda表达式
【特性】
支持将代码块作为方法参数,Lambda表达式允许使用更简洁的代码来创建只有一个抽象方法的接口(这种接口被称为函数式接口)的实例。
【组成部分】
1,形参列表
形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号都可以省略。
2,箭头(->)
3,代码块
如果代码块只包含一条语句,Lambda表达式允许省略代码块的花括号。
Lambda代码块只有一条return语句,甚至可以省略return关键字。
Lambda表达式需要返回值,而它的代码块中仅有一条省略了return语句,Lambda表达式会自动返回这条语句的值。
【Lambda表达式的类型】
被称为“目标类型”(target type),Lambda表达式的目标类型必须是“函数式接口(functional interface)”。
Lambda表达式的结果被当成对象,即返回值是对象。
【函数式接口】
函数式接口代表只包含一个抽象方法的接口。
函数式接口可以包含多个默认方法、类方法,但只能声明一个抽象方法。
【Lambda表达式的限制】
1,Lambda表达式的目标类型必须是明确的函数式接口。
2,Lambda表达式只能为函数式接口创建对象。Lambda表达式只能实现一个方法,因此它只能为只有一个抽象方法的接口(函数式接口)创建对象。
【Lambda表达式常见使用方式】
1,将Lambda表达式赋值给函数式接口类型的变量。
2,将Lambda表达式作为函数式接口类型的参数传给某个方法。
3,使用函数式接口对Lambda表达式进行强制类型转换。
【Lambda表达式的本质】
使用简洁的语法来创建函数式接口的实例——这种语法避免了匿名内部类的烦琐。
【方法引用与构造器引用】
1,引用类方法
类名::类方法
Converter converter1 = Integer::valueOf;
(a,b...) -> 类名.类方法(a,b...)
Converter converter1 = from -> Integer.valueOf(from);
2,引用特定对象的实例方法
特定对象::实例方法
Converter converter2 = "fkit.org"::indexOf;
(a,b...) -> 特定对象.实例方法(a,b...)
Converter converter2 = from -> "fkit.org".indexOf(from);
3,引用某类对象的实例方法
类名::实例方法
MyTest mt = String::substring;
(a,b...) -> a.实例方法(b...)
MyTest mt = (a,b,c) -> a.substring(b,c);
4,引用构造器
类名::new
YourTest yt = JFrame::new;
(a,b...) -> new 类名(a,b...)
YourTest yt = (String a) -> new JFrame(a);
【Lambda表达式与匿名内部类的联系和区别】
相同:
1,Lambda表达式与匿名内部类一样,都可以直接访问"effectively final"的局部变量,以及外部类的成员变量(包括实例变量和类变量)。
2,Lambda表达式创建的对象与匿名内部类生成的对象一样,都可以直接调用从接口中继承的默认方法。
区别:
1,匿名内部类可以为任意接口创建实例——不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方法即可;
但Lambda表达式只能为函数式接口创建实例。
2,匿名内部类可以为抽象类甚至普通类创建实例;
但Lambda表达式只能为函数式接口创建实例。
3,匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;
但Lambda表达式的代码块不允许调用接口中定义的默认方法。
【示例1】
class Demo
{
//该方法调用需要Eaterble对象
public void eat(Eatable e) {
System.out.println(e);
e.taste();
}
//调用该方法需要Flyable对象
public void drive(Flyable f) {
System.out.println("我正在驾驶:" + f);
f.fly("【碧空如洗的晴日】");
}
//调用该方法需要Addable对象
public void test(Addable add) {
System.out.println("5与3的和为:" + add.add(5,3));
}
public static void main(String[] args) {
Demo d = new Demo();
d.eat(()->System.out.println("苹果的味道不错!"));
d.drive(weather->
{
System.out.println("今天的天气是:" + weather);
System.out.println("直升机飞行平稳");
});
d.test((a,b)->a+b);
}
}
interface Eatable
{
void taste();
}
interface Flyable
{
void fly(String weather);
}
interface Addable
{
int add(int a, int b);
}
结果:
Demo$$Lambda$1/0x0000000100061040@2a098129
苹果的味道不错!
我正在驾驶:Demo$$Lambda$2/0x0000000100067840@6956de9
今天的天气是:【碧空如洗的晴日】
直升机飞行平稳
5与3的和为:8
【示例2】
import java.util.Arrays;
class Demo
{
public static void main(String[] args) {
String[] arr1 = new String[]{"java","fkava","fkit","ios","android"};
Arrays.parallelSort(arr1,(o1,o2) -> o1.length() - o2.length());
System.out.println(Arrays.toString(arr1));
int[] arr2 = new int[]{3,-4,25,16,30,18};
Arrays.parallelPrefix(arr2, (left,right) -> left*right);
System.out.println(Arrays.toString(arr2));
long[] arr3 = new long[5];
Arrays.parallelSetAll(arr3, operand -> operand*5);
System.out.println(Arrays.toString(arr3));
}
}
结果:
[ios, java, fkit, fkava, adnroid]
[3, -12, -300, -4800, -144000, -2592000]
[0, 5, 10, 15, 20]