假设我们要创建一个线程,用于打印“Hello world!”。在Java 8之前,我们可以通过如下的方式来实现:
1 | new Thread(new Runnable() { |
在Java 8以后,可以使用lambda表达式来简写:
1 | new Thread(() -> System.out.println("Hello world!")).start(); |
函数式接口
函数式接口:只有一个抽象方法的接口。
在Java 8中,新增了一个注解@FunctionalInterface,用于标识函数式接口。
java.lang.Runnable就是一个函数式接口,其源码如下:
1 |
|
Lambda表达式
在接受函数式接口的地方可以使用Lambda表达式。语法如下:
1 | (parameters) -> expression |
或者
1 | (parameters) -> { statements; } |
示例:
1.没有参数
1 | Runnable r = () -> System.out.println("Hello world!"); |
2.一个参数
1 | Predicate<String> p = (String s) -> s.isEmpty(); |
3.两个参数
1 | List<User> list = new ArrayList<>(); |
4.方法体多于1行
1 | list.sort((Apple a, Apple b) -> { |
使用局部变量
lambda表达式允许使用外部变量。但局部变量必须显式声明为final,或者事实上是final。
1 | // 显式声明为final |
或者
1 | // 事实上是final:只赋值一次 |
下面的代码无法编译,将报错误:Local variable x defined in an enclosing scope must be final or effectively final
1 | int x = 33; |
方法引用
当Lambda表达式中只是直接调用一个方法时,我们可以采用方法引用,重用已有的方法定义。
静态方法。语法为
类名::方法名
。例如,Integer::parseInt
。实例方法。语法为
类名::方法名
。例如,String::length
。现存对象的实例方法。例如,
this::isEmpty
。构造函数引用。语法:
类名::new
。例如,String::new
。
示例:
1.遍历列表
1 | List<String> list = new ArrayList<>(); |
2.排序:按照重量对苹果进行升序排序,如果重量相等,则按照原产国排序
1 | list.sort((Apple a, Apple b) -> { |
采用方法引用重写:
1 | list.sort(Comparator.comparing(Apple::getWeight) |