在 Java8 之前,当实现只有一个方法的接口,我们通常是通过使用匿名内部类的方式来重写接口的方法,以 Comparator 为例:
1 2 3 4 5 6 7 8
| List<Integer> list = Arrays.asList(1, 3, 5, 2, 4, 6); Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } }); System.out.println(list);
|
Java8 中引入了 Lambda 表达式,提供了更加简洁的语法:() -> {}
1 2 3 4 5
| List<Integer> list = Arrays.asList(1, 3, 5, 2, 4, 6); Collections.sort(list, (Integer o1, Integer o2) -> { return o1.compareTo(o2); }); System.out.println(list);
|
从 Java8 开始编译器可以从接口的方法签名中自动推导出参数类型,因此可以省略掉类型的声明
1 2 3 4 5
| List<Integer> list = Arrays.asList(1, 3, 5, 2, 4, 6); Collections.sort(list, (o1, o2) -> { return o1.compareTo(o2); }); System.out.println(list);
|
当方法体只有一行代码时,可以省略掉 {} 和 return 关键字以及代码行结束的分号“;”
1 2 3
| List<Integer> list = Arrays.asList(1, 3, 5, 2, 4, 6); Collections.sort(list, (o1, o2) -> o1.compareTo(o2)); System.out.println(list);
|
对于只有一个抽象方法的接口,都可以使用 Lambda 表达式。为了确保接口符合要求,可以使用 @FunctionalInterface 注解标注接口,被 @FunctionalInterface 注解标注的接口(称为函数式接口),只允许存在一个抽象方法,没有或多于一个抽象方法,编译都将无法通过。由于默认的方法不是抽象的,因此,函数式接口依然可以存在一个或多个默认方法。其中,每个 Lambda 表达式都将匹配函数式接口的这个抽象方法,Lambda 表达式的类型也由该接口类型决定。
1 2 3 4 5 6
| @FunctionalInterface interface Operation<I, O> { O calculate(I input); }
|
对函数式接口使用 Lambda 表达式
1 2 3 4 5
| public static void main(String[] args) { Operation<Integer, Integer> square = (i) -> i * i; Integer result = square.calculate(3); System.out.println(result); }
|