什么是函数式接口(传递行为,而不仅仅是值):
- 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。
- 我们在某个接口上申明了 java.lang.FunctionalInterface注解,那么编译器会按照函数式接口的定义来要求该接口。
- 如果某个接口只有一个抽象方法,但是我们并没有给该接口申明 java.lang.FunctionalInterface注解,那么编译器依然会将该接口看作是函数式接口。
函数式接口申明注解(java.lang.FunctionalInterface)。这是一种声明式注解,用于去表示某一个接口的类型的申明用来表示函数式接口,该函数式接口是由java语言来规范定义的。
从概念上来说,函数式接口只有一个抽象方法。因为 java.lang.reflect.Method#isDefault() 方法有一个默认的实现,所以它们不是抽象的,如果接口声明了一个抽象方法,并且重写了 java.lang.Object 的任何一个 public 的方法,则该方法也不计入接口的抽象方法计数,因为接口的任何实现都会有 java.lang.Object 类的实现或其他地方的实现。
需要注意的是,函数式接口的实例可以使用 lambda 表达式,方法引用或者构造方法引用来创建。
如果使用了该注解类型对一个类或接口进行标记,如果不满足以下条件,则编译器需要生成错误信息:
- 类型是一个接口类型,但是并不是注解类型,枚举或者类。
- 被注解的类型满足了函数式接口的要求。
但是,编译器将把满足函数式接口定义的任何接口都视为函数式接口,而不管接口中声明是否存在该注解。lambda 是一个直接继承至object的一个类。是由动态字节码生成的,有点类似于动态代理。
自定义函数式接口的申明方式:
// 如果接口声明了一个抽象方法,并且重写了 java.lang.Object
// 的任何一个 public 的方法,则该方法也不计入接口的抽象方法计数
// 对于该说明的演示内容
// 这是一个标准的函数式接口
@FunctionalInterface
public interface TestInterface {
void test();
}
// 编译报错, 报错的内容为:
//Multiple non-overriding abstract methods found in interface TestInterface
@FunctionalInterface
public interface TestInterface {
void test();
void test2();
}
// 需要注意这种情况的存在,如果接口中重写了 java.lang.Object 的任何一个 public
// 的方法,那么该方法不会被纳入计数的,因为子类会实现接口中的所有抽象方法,
// 在java语言中,如果接口中的方法与 object 的 public 方法名字一样的话,默认是
// 认为直接继承至 object 的,所以不会被纳入计数
@FunctionalInterface
public interface TestInterface {
void test();
String toString();
}
在理解了函数式接口之后,接下来需要看 java 为我们提供的四大内置最核心的函数式接口以及基于他们衍生的一些很常用的函数式接口,lambda 的声明需要使用到这些相关的函数式接口,并且jdk内置的工具都会大量用到这些函数式接口。所以这里需要先看这些函数式接口,具体请看下一篇文章: