本篇文章中以Java 8的环境来讲解。
1 函数式接口
当接口中存在且仅存在一个抽象方法时,这样的接口就称为函数式接口。(变量,默认方法,静态方法没有限制)。接口中的静态方法一定要有方法体,所以接口中的静态方法不是抽象方法。而接口中的默认方法也必须要有方法体,所以接口中的默认方法也不是抽象方法。
说明:如果接口中的方法签名与Object类中的共有(public)方法相同,则接口中的该方法不算是抽象方法。
函数式接口里面可以出现并且如果出现就只可以出现Object类的public访问权限的非final的方法。(可以出现native方法),这样的方法只有hashcode,equals,toString这三个方法。
我们可以使用@FunctionalInterface注解来标记一个函数式接口,当该接口不是函数式接口时,会产生编译错误。
如下:虽然这个接口有很多方法,但仍然是一个函数式接口。这个抽象方法为output,带有一个参数,参数的类型为String,想要实现输出类型为String的字符串。
FunctionalInterface.java
package cn.ancony.test;
/** * 如果书写函数式接口,这个注解最好加上,可以让编译器 * 来检查这个接口是不是函数式接口。 */ @java.lang.FunctionalInterface public interface FunctionalInterface { //只有一个抽象方法 void output(String name);
//看上去像抽象方法,但是这个方法是Object里面的方法。 //不算抽象方法,下面的hashCode和toString方法也是。 boolean equals(Object var1);
int hashCode();
String toString();
//静态方法,有方法体,不是抽象方法 //该类型的方法没有方法体是不能通过编译的 static void method() { }
//默认方法,有方法体,不是抽象方法 //该类型的方法没有方法体是不能通过编译的 default void method2() { } } |
Lambda表达式的结果类型就是函数式接口类型。确切的说,结果类型是一个实现了函数式接口类型的对象。
Lambda表达式就是用来实现函数式接口的。它实现的就是接口里面的那个唯一确定的抽象方法。
2 Lambda表达式
Lambda表达式的结果类型(目标类型)必须是函数式接口类型。
Lambda表达式的语法格式:
(参数列表) -> {方法体;}
Test.java
package cn.ancony.test;
public class Test { public static void main(String[] args) { //Lambda表达式的标准写法 deal((String name) -> { System.out.print(name); }); //省略了参数类型 deal((name) -> { System.out.print(name); }); //方法体只有一条语句,省略了大括号。 //省略大括号的同时还要省略语句的结束符号(;) deal((name) -> System.out.print(name)); //参数只有一个,可以同时省略方法签名的参数类型和小括号。 deal(name -> System.out.print(name)); //参数可以使用任何符合变量声明规则的符号表示 deal(any -> System.out.print(any)); }
//将上面声明的这个接口作为参数传进来。 //方法体为要操作的具体内容,具体怎么操作, //使用Lambda表达式来实现。 public static void deal(FunctionalInterface fi) { fi.output("Ancony"); } } |
Lambda表达式书写时的省略原则:
1 Lambda表达式参数列表的类型可以省略。
2 当参数格式只有一个的时候,()可以省略。
3 当方法存在返回值,并且方法体只有一条语句时,{}与return可以同时省略。
4 当方法没有返回值,并且方法体只有一条语句时,{}可以省略。
对上面的例子稍作修改,使用一个有返回值的抽象方法的函数式接口作为例子。
FunctionalInterface.java
package cn.ancony.test;
@java.lang.FunctionalInterface public interface FunctionalInterface { String output(String name); } |
Test.java
package cn.ancony.test;
public class Test { public static void main(String[] args) { //Lambda表达式的标准写法 deal((String name) -> { return name; }); //大括号和return要么同时省略,要么同时使用。 //同时省略的时候,要把“;“省略。 deal((name) -> name); //省略小括号 deal(name->name); //参数可以使用任何符合变量声明规则的符号表示 deal(_xx2 -> _xx2); }
public static String deal(FunctionalInterface fi) { //将接口的返回值作为deal方法的返回值。 return fi.output("Ancony"); } } |