函数式编程
面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是怎么做。
有时只是为了做某事情而不得不创建一个对象,而传递一段代码才是我们真正的目的。
Lambda
Lambda是一个匿名函数,可以理解为一段可以传递的代码。
当需要启动一个线程去完成任务时, 通常会通过java.lang.Runnable接口来定义任务内容,并使用java.lang.Thread类来启动该线程
传统写法,代码如下:- public class Demo {
- public static void main(String[] args) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("多线程任务执行!");
- }
- }).start();
- }
- }
复制代码 借助Java 8的全新语法,上述Runnable接口的匿名内部类写法可以通过更简单的Lambda表达式达到同样的效果:- public class Demo04LambdaRunnable {
- public static void main(String[] args) {
- new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程
- }
- }
复制代码Lambda的优点 简化匿名内部类的使用,语法更加简单。
前提条件
必须是接口, 接口中有且只有一个抽象方法
有且仅有一个抽象方法的接口,称为函数式接口。
格式
Lambda表达式的标准格式为:- () -> {}
- () 参数列表,无参数留空
- -> 固定写法, 代表指向动作
- {} 方法体
复制代码 省略规则
在Lambda标准格式的基础上,使用省略写法的规则为:
- 参数类型可省略
- 如果只有一个参数 ()可以省略
- 如果方法体只有一句话 return 大括号 分号都可省略, 但必须同时省略
- new Thread(() -> System.out.println("省略格式开启线程")).start();
复制代码 原理
- 在匿名方法所在类中新增一个方法,方法体为Lambda表达式中的代码
- 运行时形成一个新的类,并实现对应接口
- 重写方法的方法体中调用匿名方法所在类中新生成的方法.
函数式接口
函数式接口在Java中是指:有且仅有一个抽象方法的接口。
函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。
从应用层面来讲,Java中的Lambda可以看做是匿名内部类的简化格式,但是二者在原理上不同。
格式
只要确保接口中有且仅有一个抽象方法即可:- 修饰符 interface 接口名称 {
- public abstract 返回值类型 方法名称(可选参数信息);
- }
复制代码 由于接口当中抽象方法的public abstract是可以省略的,所以定义一个函数式接口很简单:- public interface MyFunctionalInterface {
- void myMethod();
- }
复制代码 @FunctionalInterface
@FunctionalInterface 该注解可用于一个接口的定义上:- @FunctionalInterfacepublic interface MyFunctionalInterface {
- void myMethod();
- }
复制代码 一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。不过,即使不使用该注解,只要满足函数式接口的定义,这仍然是一个函数式接口
常用函数式接口
Supplier接口
java.util.function.Supplier接口,它意味着"供给" , 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
抽象方法:
T get() 用来获取一个泛型参数指定类型的对象数据
求数组元素最大值
使用Supplier接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值- public class supplierInterface {
- public static void main(String[] args) {
- int[] arr = {3,24,346,4,13};
- method(() -> {
- Arrays.sort(arr);
- return arr[arr.length - 1];
- });
- }
- public static void method(Supplier<Integer> s) {
- Integer max = s.get();
- System.out.println(max);
- }
- }
复制代码 Consumer接口
java.util.function.Consumer 接口不生产数据,而是消费一个数据,其数据类型由泛型参数决定
抽象方法
void accept(T t),意为消费一个指定泛型的数据
默认方法
default Consumer andThen(Consumer |