函数式接口(也叫SAM接口,Single Abstract Method)的对象可以作为函数的参数,这样参数在引用时,可以以lambda表达式的方式出现。
每个函数式接口里仅允许有一个抽象方法,这个方法叫做函数式方法,lambda表达式的参数和返回类型必须和该函数的参数和返回类型保持一致。你无须去创建这个类,编译器会帮你实现。
函数式接口仅允许有一个抽象方法,用注解@FunctionalInterface 标识,如果不写默认也是函数式接口
- 仅允许有一个抽象方法
@FunctionalInterface
public interface CallBack<T> {
T callback();
}
因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的
- 接口里有一个默认方法
@FunctionalInterface
public interface CallBack<T> {
T callback();
default void method1(){
System.out.println();
}
default void method2(){
System.out.println();
}
default void method3(){
System.out.println();
}
}
- 函数式接口里允许定义静态方法
函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的,静态方法默认是public的
@FunctionalInterface
public interface CallBack<T> {
T callback();
static void method(){
}
static void method2(){
}
}
- 函数式接口的使用
我自定义了ReentranReadLock类,其中定义了readLock方法来对所做的事情进行前置加锁,后置解锁的效果
public class ReentranReadLock {
private final ReentrantReadWriteLock locker;
public ReentranReadLock() {
locker = new ReentrantReadWriteLock();
}
public <T> T readlock(CallBack<T> callBack){
this.locker.readLock().lock();
Object object;
try {
//lambda表达式的调用
object = callBack.callback();
}finally {
this.locker.readLock().unlock();
}
return (T) object;
}
}
测试代码
public class MyTest {
private static String str = "hello world";
public static void main(String[] args) {
ReentranReadLock readLock = new ReentranReadLock();
//lambda表达式相当于是callback方法的重写
String result = readLock.readlock(() -> str);
System.out.println(result);
}
}
多线程Runable接口就是函数式接口,只有一个抽象方法run,所以可以使用lambda表达式来简化,我看有博客介绍说能替代内部类,这个说法不太准确,Runable接口使用如下
//不使用lambda表达式
new Thread(
new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
}
).start();
//使用lambda表达式
new Thread(() -> System.out.println("hello")).start();
总结,其实我调用的时候,相当于我把接口CallBack接口当参数传进来,函数式接口中只有一个抽象方法,所以lambda表达式相当于对这个抽象方法进行了重写。我的这个例子实现了对目标进行前置后置操作,我的理解有点像AOP编程,是不是很牛逼。