一、函数式接口
简单点说就是有且仅有一个抽象方法的接口,Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
@FunctionalInterface(定义一个函数式接口)
二、语法结构
(o1,o2) -> Integer.compare(o1,o2);
- ->是Lambda操作符或箭头操作符
- ->左边是Lambda形参列表(其实就是接口中的抽象方法的形参列表)
- ->右边是lambda体(Lambda 表达式要执行的功能/重写的接口的方法)
三、使用方法
@FunctionalInterface
interface Text { void te(int num); }
// Lambda表达式实现了Text接口的te方法
Text lambda = (a, b) -> System.out.println(a + b);
// 使用了Lambda表达式
lambda.te(10, 20);
四、简化lambda表达式
-
可选类型声明
不需要声明参数类型,编译器可以统一识别参数值。
-
可选的参数圆括号
一个参数无需定义圆括号,但多个参数需要定义圆括号。
-
可选的大括号
如果主体包含了一个语句,就不需要使用大括号。
-
可选的返回关键字
如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
五、变量作用域
-
可以直接在 Lambda 表达式中访问外层的局部变量;
-
在 Lambda 表达式当中被引用的变量的值不可以被更改;
(本质上因为lambda用的是内部类)
-
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数
(包括参数的名称也不能一样)
六、四大内置函数接口
1.Consumer<T>:消费型接口
(1.)含义:这个接口代表一个接受单个输入参数并且没有返回值的操作。
它包含一个抽象方法accept(T t),用于对传入的参数执行某种操作。
它常用于遍历集合等场景,对集合中的每个元素执行相同的操作。
(2.) 示例:示例:Consumer<String> printer = System.out::println;,
然后可以使用printer.accept("Hello World!");输出字符串。
2.Supplier<T>:供给型接口
(1.)含义:这个接口代表一个没有输入参数,但能够返回一个结果的供应商。
它包含一个抽象方法get(),用于获取一个结果。
(2.) 示例:Supplier<Integer> randomSupplier = () -> new Random().nextInt();,
然后可以使用randomSupplier.get()获取一个随机整数。
3.Function<T, R>:函数型接口
(1.)含义:这个接口代表一个接受一个参数并产生结果的函数,它包含一个抽象方法apply(T t),用于对输入的参数应用某种操作并返回一个结果。
(2.)示例:Function<String, Integer> stringToInteger = Integer::valueOf;,
然后可以使用stringToInteger.apply("123")将字符串转换为整数。
4.Predicate<T>:断言型接口
(1.)含义:这个接口代表一个接受一个参数并返回一个布尔值的断言。它包含一个抽象方法test(T t),用于对传入的参数进行某种测试,并返回测试结果。
(2.)示例:Predicate<String> isEmpty = String::isEmpty;,
然后可以使用isEmpty.test("")检查字符串是否为空。
2.方法引用
双冒号:: 为引用运算符。如果Lambda要表达的函数方案已经存在于某 个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
3.构造方法引用
格式:类名::new
抽象方法中,创建对象
抽象方法的参数要和构造方法参数一致
4.静态方法引用
格式: 类名::静态方法名
本质上要求: 接口中的方法调用了另一个类的静态方法。
要求两个方法的参数要一致。
5.实例方法引用
格式: 对象名::方法名
本质上要求: <font color='red'>接口的方法</font>
调用了<font color='red'>对象的方法</font>。
要求两个方法的参数要<font color='red'>一致</font>。
5.对象方法引用
格式: 类名::方法名
条件:在抽象方法中,参数作为实例方法调用者,就可以简化