函数式接口是什么?
先来看看传统的创建线程是怎么写的
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("你好");
}
});
t1.start();
}
再来看看使用了函数式接口是怎么写的
public static void main(String[] args) {
Thread t1 = new Thread(()->System.out.println("你好"));
t1.start();
}
Runnable接口直接可以使用Lambda表达式来编写,这是因为Runnable接口是一个函数式接口,来看看Runnable的源码。
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since JDK1.0
*/
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
发现该接口加上了函数式接口的定义注解@FunctionalInterface
,表明该接口是一个函数式接口。
在JDK 8中,除了Runnbale接口,还有像Comparator、Callable 等接口都加上了该注解定义为函数式接口。
函数式接口规范
-
@Functionallnterface标识为一个函数式接口只能用在只有一个抽象方法的接口上。
-
接口中的静态方法、默认方法、覆盖了Object类的方法都不算抽象方法。
-
@Functionallnterface 注解不是必须的,如果该接口只有一个抽象方法可以不写,它默认就符合函数式接口,但建议都写上该注解,编译器会检查该接口是否符合函数式接口的规范。
举例说明
正确的函数式接口
@FunctionalInterface
public interface Test<N,V>{
V Test(N n1,N N2);
}
加了几个符合函数式的方法也没事,编译器也不会报错。
@FunctionalInterface
public interface Test<N,V>{
V Test(N n1,N n2);
boolean equals(Object o);
default void defaultMethod(){
}
static void staticMethod(){
}
}
这个没用@Functionallnterface函数式接口,有两个抽象方法,不能用于Lambda表达式。
public interface Test<N,V>{
V Test1(N n1,N n2);
V Test2(N n1,N n2);
}
这个有两个抽象方法的用@Functionallnterface注解的函数式接口编译会报错。
@FunctionalInterface //这里编译器会提醒红色波浪线
public interface Test<N,V>{
V Test1(N n1,N n2);
V Test2(N n1,N n2);
}
这个没有一个抽象方法,用@Functionallnterface注解的函数式接口编译报错。
@FunctionalInterface
public interface Test<N,V>{
}