java8 函数式接口(FunctionalInterface) [一]

时间:2021-01-18 19:10:54

函数式接口代表的一种契约, 一种对某个特定函数类型的契约。 在它出现的地方,实际期望一个符合契约要求的函数。 Lambda表达式不能脱离上下文而存在,它必须要有一个明确的目标类型,而这个目标类型就是某个函数式接口。
引用参考资料中的内容

函数式接口是java8新增的,它跟普通的接口的定义不同之处在于:它只定义唯一一个抽象方法(Single Abstract Method (SAM))。可以使用lambda表达式编写。

网络上对于lambda表达式和函数式接口的说明有很多了,但是在看完之后,依然对函数式接口的创建和使用不是很理解,所以找了些资料,整理记录下来,以便加深理解。

本文中主要介绍有以下几点:
1. 唯一抽象方法的定义是什么。
2. 如何使用创建自己的函数式接口。
3. 如何使用lambda表达式编写函数式接口。

函数式接口是长这样子的

@FunctionalInterface
public OneFunctionalInterface{
void action();
}

OneFunctionalinterface接口只有一个抽象方法,所以它是一个函数式接口。
下面给出一个不是函数式接口的例子

//Not Function Interface, will be compile error
@FunctionalInterface
public NotFunctionalInterface{
void action();
void invoke();
}

NotFunctionalInterface接口会编译不能过,因为它使用@FunctionalInterface标记是函数式接口,但是它有两个抽象方法,因此不符合函数式接口的要求。

接口是特殊的抽象类,在java中,所有类都是Object的子数,所以函数式接口可以包含Object类中的public方法。

@FunctionalInterface
public interface TwoFunctionalInterface{
void action();

//Object's public methods
String toString();
int hashCode();
boolean equals(Object o);
}

TwoFunctionalInterface接口依然是函数式接口,如果包含Object的非public方法(如:void finalize()),就会出错。

//Not Function Interface, will be compile error
@FunctionalInterface
public interface NotFunctionalInterfaceTwo{
void action();

//Object's protected methods
void finalize();
}

NotFunctionalInterfaceTwo接口中的finalize()方法虽然也是Object中的方法,但它是被protected关键字修饰的,所以NotFunctionalInterfaceTwo不能被定义为函数式接口。

函数式接口可以包含静态方法
在java8以前,静态方法只能在类中定义,在java8中,接口可以定义静态方法。静态方法不是抽像方法,所以函数式接口可以包含一个或多个静态方法。

@FuncationalInterface
public interface ThreeFunctionalInterface{
void action();
static void dosomethings(){
System.out.println("write words.");
}
}

ThreeFunctionalInterface接口中包含一个抽象方法action(),和一个静态方法dosomethings(),它依然还是函数式接口。

函数式接口可以包含默认方法
java8中允许使用关键default定义默认接口,因为默认方法有具体的实现,不是抽象方法,所以函数式接口可以有一个或多个默认方法。

@FunctionalInterface
public interface FourFunctionalInterface{
void action();
default String hello(){
return "world";
}
}

接口继承
我们都知道接口是可以继承的,如果父接口是一个函数式接口,那么子接口也可能是一个函数式接口。

@FunctionalInterface
public SubFunctionalInterface extends FourFunctionalInterface{

}

SubFunctionalInterface接口依然是一个函数式接口。

如果在子接口中,定义另一个抽象接口,它就不再是函数式接口了。

//Not Function Interface, will be compile error
@FunctionalInterface
public interface NotSubFunctionalInterface extends FourFunctionalInterface{
void action2();
}

NotSubFunctionalInterface接口继承FourFunctionalInterface接口,FourFunctionalInterface接口拥有一个抽象方法action(),NotSubFunctionalInterface又定义了另一个抽象方法action2(),那么NotSubFunctionalInterface拥有两个抽象方法,所以它不是一个函数式接口。

运行函数式接口
下面新建一个函数式接口, 并使用lambda表达式创建实例。

@FunctionalInterface
public interface MyHandler{
void action();
defaul String hello(){
retrun "world";
}
}

编写测试类

public class FunctionalInterfaceTest{
public static void main(String... args){
System.out.println("create Functional Interface");
MyHandler h = ()->{System.out.println("print by action();")};
h.action();
System.out.println(h.hello());
System.out.println("end of test.");
}
}

运行结果

create Functional Interface
print by action();

world
end of test.

总结

  • 函数式接口只能包含一个抽象方法
  • 函数式接口可以包含Object类中所有public修饰的方法
  • 函数工接口可以包含一个或多个静态方或默认方法

这一篇简单的介绍函数式接口的定义,对函数式接口有个大概的了解,下一篇将介绍函数式接口继承时对方法签名的判断,以及声明异常。