聊聊对 FunctionalInterface 注解的一些理解

在看 Tomcat 代码过程中碰到了一个小问题,可以用代码来举例讲一下
先定义一个简单的接口

1
2
3
4
5
@FunctionalInterface
public interface FunctionalInterfaceTest {

String getInfo();
}

functionalInterface本质还是个接口,所以可以用类实现接口的方式
比如像这样

1
2
3
4
5
6
public class FunctionalInterfaceImpl implements FunctionalInterfaceTest{
@Override
public String getInfo() {
return "info";
}
}

但是有下面另外两种方式也是可以实现接口的
第一种是 lambda,

1
2
FunctionalInterfaceTest interfaceTest = () -> "aaa";
System.out.println(interfaceTest.getInfo());

这个实现方式就是直接把 lambda 表达式作为接口实现,但是如果这样就要注意如果实在代码中间的话,debug 还是会跳到这个 lambda 的实现,有时候会混乱,因为只是跳转到 lambda 表达式,而不是所在的方法
第二种是这样

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
FunctionalInterfaceTest interfaceTest1 = demo.getSelfInfo();
System.out.println(interfaceTest.getInfo());
}

public FunctionalInterfaceTest getSelfInfo() {
return this::info;
}

public String info() {
return "ccc";
}

前面 getSelfInfo 的返回值就是类里的一个方法,可以用来作为 FunctionalInterface 的实现,这里跟上面有个比较奇怪的,或者说对于常规的接口理解,一般来说实现的方法签名必须和接口的方法签名一致,但是对于函数接口,私域就突破了这个限制,不管是lambda 这种匿名函数或者后面这种方法引用,都没有用 getInfo 这个方法名,这也是一个比较最近的一个理解。