函数式接口:
只包含一个抽象方法的接口。函数式接口可以包含多个默认方法、类方法,但只能包括一个抽象方法。
Java8提供了@FunctionalInterface注解,该注解放在接口定义前面,表示该接口是函数式接口,编译时会检查该接口是否符合函数式接口的要求。
Lambda表达式可以实现函数式接口,并在实现处创建一个对象,和匿名内部类相似。
区别:匿名内部类可以实现任何接口、抽象类,但Lambda表达式只能实现函数式接口。Lambda表达式相当于一种特殊的匿名内部类,但Lambda表达式比匿名内部类更加简洁。
Lambda表达式只是语法糖,编译时会被替换为常规的代码。
Lambda表达式语法:
(形参表) -> {
.......//抽象方法的实现部分
}
无形参时,写为();只有一个形参时,可以缺省()。
代码块中只有一条语句时,可以缺省{};代码块中只有一条return语句时,可以缺省{}和return关键字(要缺省,必须同时缺省return关键字和{})。
参数表只写形参变量名,不写形参类型。
示例:
1 package test; 2 3 interface Interface1{ 4 //无形参、无返回值 5 void print(); 6 } 7 8 interface Interface2{ 9 //有形参 10 void print(String str); 11 } 12 13 interface Interface3 { 14 //有返回值 15 String getString(); 16 } 17 18 public class Test { 19 public static void main(String[] args) { 20 Interface1 interface1=()->{ 21 System.out.println("接口1 ok"); 22 }; 23 interface1.print(); 24 25 //只有一个形参时,可以缺省();代码块只有一条语句时,可以缺省{} 26 Interface2 interface2=str-> System.out.println(str); 27 interface2.print("接口2 ok"); 28 29 //方法体中只有一条return语句时,可以同时缺省{}和return关键字,要缺省就必须同时缺省这两部分 30 Interface3 interface3=()-> "接口3 ok"; 31 String str=interface3.getString(); 32 System.out.println(str); 33 } 34 }
Lambda表达式会在该处创建一个该接口的示例,并返回这个实例,即Lambda表达式的值是对应接口的实例。
可以将Lambda表达式作为实参传递给方法:
1 package test; 2 3 interface Interface3 { 4 //有返回值 5 String getString(); 6 } 7 8 public class Test { 9 public static void main(String[] args) { 10 //可以将Lambda表达式作为实参传递给方法。Lambda表达式的值是对应接口的实例,并不是所实现抽象方法的返回值String。Lambda表达式比匿名内部类更简洁。 11 printStr(()->"ok"); 12 } 13 14 public static void printStr(Interface3 interface3){ 15 System.out.println(interface3.getString()); 16 } 17 }
Java中的很多接口都是函数式接口,比如ActionListener接口、Runnable接口。
Lambda表达式可访问的变量和匿名内部类可访问的变量完全一致,但Lambda表达式不能调用接口中定义的默认方法,匿名内部类则可以。