系列文章目录
文章目录
1.函数式接口
1.1 函数式接口的概念
在一个接口中,抽象方法只能有一个,可以有其他的非抽象方法:如static
、default
方法。
定义一个函数式接口很简单:
public interface MyFunctionalInterface {
// 唯一一个的抽象方法
void myMethod();
// 默认方法
default void myMethod(){
sout("我是默认方法");
}
}
1.2 @FunctionalInterface注解
与 @Override
注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface
。该注 解可用于一个接口的定义上:
@FunctionalInterface
public interface MyFunctionalInterface {
void myMethod();
}
【注意】:
-
一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。
-
需要注意的是,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口,使用起来都一样。
2.函数式编程
函数式接口的可以被用于函数式编程,用来简化代码的编写,函数式编程的体现 就是使用Lambda
表达式 和 方法引用 来简化代码编写。
2.1 函数式接口典型使用场景代码示例:
函数式接口典型使用场景就是:函数式接口作为方法定义的形参,Lambda
作为方法调用时的入参。
public class DemoMain09 {
public static void main(String[] args) {
// 调用参数为 函数式接口的方法。
// 方法入参列表 -> 方法体
doSomething(() ‐> System.out.println("Lambda执行啦!"));
}
// 方法定义的形参为 函数式接口类型
private static void doSomething(MyFunctionalInterface inter) {
// 调用函数式接口中的方法
inter.myMethod();
}
}
2.2 示例2:
例如:java.lang.Runnable
接口就是一个函数式接口,假设有定义一个方法 startThread()
,它的形参就是Runnable
接口类型,那么就调用方法startThread()
时的入参就可以使用Lambda表达式。这种情况其实和 调用Thread 类的构造方法 入参为 Runnable接口的实现类对象 没有本质区别。
public class Demo04Runnable {
private static void startThread(Runnable task) {
new Thread(task).start();
}
public static void main(String[] args) {
startThread(() ‐> System.out.println("线程任务执行!"));
}
}
3.JDK提供的常用的函数式接口
JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function
包中被提供。
下面是最简单的4个接口及使用示例。
*1、供给型接口:Supplier<R> R get(); 该接口用于返回一个泛型R类型的对象。
*2、消费型接口:Comsumer<R> accept(R); 传入一个泛型R类型的参数,把参数使用掉。
*3、函数型接口:Function<R,T> T apply<R>; 传入一个泛型R类型的参数,返回一个泛型T类型的对象。
*4、断言型接口:predicate<R> boolean test(R); 传入一个泛型R类型的参数,返回一个boolean类型的判断结果
函数式接口的好处就是将方法的处理逻辑 参数化,方法的处理逻辑 和 调用该方法的代码之间是解耦的。
代码示例:
public class Demo11FunctionApply {
private static void method(Function<String, Integer> function) {
// 方法调用执行。
int num = function.apply("10");
System.out.println(num + 20);
}
public static void main(String[] args) {
// 传一个Lambda表达式逻辑
method(s ‐> Integer.parseInt(s));
}
}
4.方法引用
双冒号 ::
为引用运算符,而它所在的表达式被称为方法引用。
如果Lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
如果使用Lambda,那么根据“可推导就是可省略”的原则,无需指定参数类型,也无需指定的重载形式——它们都
将被自动推导。而如果使用方法引用,也是同样可以根据上下文进行推导。
1、通过类名引用静态方法
对比下面两种写法,完全等效:
Lambda表达式: s -> System.out.println(s);
方法引用写法: System.out::println
Lambda表达式: n -> Math.abs(n)
方法引用: Math::abs
2、通过对象名引用成员方法
MethodRefObject obj = new MethodRefObject();
printString(obj::printUpperCase);
3、引用当前类中的成员方法
Lambda表达式: () -> this.buyHouse()
方法引用: this::buyHouse
4、类的构造器引用
Lambda表达式: name -> new Person(name)
方法引用: Person::new