1. Lambda表达式
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。可以使代码变的更加简洁紧凑。
1.1 基本语法:
(参数列表) -> {代码块}
需要注意:
- 参数类型可省略,编译器可以自己推断
- 如果只有一个参数,圆括号可以省略
- 代码块如果只是一行代码,大括号也可以省略
- 如果代码块是一行,且是有结果的表达式,
return
可以省略
注意:事实上,把Lambda表达式可以看做是匿名内部类的一种简写方式。当然,前提是这个匿名内部类对应的必须是接口,而且接口中必须只有一个函数!Lambda表达式就是直接编写函数的:参数列表、代码体、返回值等信息,用函数来代替完整的匿名内部类
!
1.2 用法示例
示例1:多个参数
准备一个集合:
// 准备一个集合
List<Integer> list = Arrays.asList(10, 5, 25, -15, 20);
假设我们要对集合排序,我们先看JDK7的写法,需要通过匿名内部类来构造一个Comparator
:
// Jdk1.7写法
Collections.sort(list,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(list);// [-15, 5, 10, 20, 25]
如果是jdk8,我们可以使用新增的集合API:sort(Comparator c)
方法,接收一个比较器,我们用Lambda来代替Comparator
的匿名内部类:
// Jdk1.8写法,参数列表的数据类型可省略:
list.sort((i1,i2) -> { return i1 - i2;});
System.out.println(list);// [-15, 5, 10, 20, 25]
对比一下Comparator
中的compare()
方法,你会发现:这里编写的Lambda表达式,恰恰就是compare()
方法的简写形式,JDK8会把它编译为匿名内部类。是不是简单多了!
别着急,我们发现这里的代码块只有一行代码,符合前面的省略规则,我们可以简写为:
// Jdk8写法
// 因为代码块是一个有返回值的表达式,可以省略大括号以及return
list.sort((i1,i2) -> i1 - i2);
示例2:单个参数
还以刚才的集合为例,现在我们想要遍历集合中的元素,并且打印。
先用jdk1.7的方式:
// JDK1.7遍历并打印集合
for (Integer i : list) {
System.out.println(i);
}
jdk1.8给集合添加了一个方法:foreach()
,接收一个对元素进行操作的函数:
// JDK1.8遍历并打印集合,因为只有一个参数,所以我们可以省略小括号:
list.forEach(i -> System.out.println(i));
实例3:把Lambda赋值给变量
Lambda表达式的实质其实还是匿名内部类,所以我们其实可以把Lambda表达式赋值给某个变量。
// 将一个Lambda表达式赋值给某个接口:
Runnable task = () -> {
// 这里其实是Runnable接口的匿名内部类,我们在编写run方法。
System.out.println("hello lambda!");
};
new Thread(task).start();
不过上面的用法很少见,一般都是直接把Lambda作为参数。
示例4:隐式final
Lambda表达式的实质其实还是匿名内部类,而匿名内部类在访问外部局部变量时,要求变量必须声明为final
!不过我们在使用Lambda表达式时无需声明final
,这并不是说违反了匿名内部类的规则,因为Lambda底层会隐式的把变量设置为final
,在后续的操作中,一定不能修改该变量:
正确示范:
// 定义一个局部变量
int num = -1;
Runnable r = () -> {
// 在Lambda表达式中使用局部变量num,num会被隐式声明为final
System.out.println(num);
};
new Thread(r).start();// -1
错误案例:
// 定义一个局部变量
int num = -1;
Runnable r = () -> {
// 在Lambda表达式中使用局部变量num,num会被隐式声明为final,不能进行任何修改操作
System.out.println(num++);
};
new Thread(r).start();//报错