Java8函数式接口
Java8自带的函数式接口
| 函数接口 | 抽象方法 | 功能 | 参数 | 返回值类型 | 示例 |
|---|---|---|---|---|---|
| Predicate |
test(T t) | 判断真假 | T | Boolean | 小明的身高大于185CM吗 |
| Consumer | accept(T t) | 消费消息 | T | void | 输出一个值 |
| Function | R apply(T t) | 将T映射为R(转换功能) | T | R | 获得Student对象的名称 |
| Supplier | T get() | 生成消息 | T | 工厂方法 | |
| UnaryOperator | T apply(T t) | 一元操作 | T | T | 逻辑非 |
| BinaryOperator | apply(T t,U u) | 二元操作 | (T,T) | (T) | 求两个数的乘机 |
编程实现
/*** 测试Lambda函数接口** @author zukxu* CreteTime 2021/7/17 0017 00:18*/public class TestLambda {public static void main(String[] args) {Student student = new Student().setName("小明").setAge(23).setHeight(180);// 判断真假 PredicatePredicate<Integer> pred = x -> x > 185;System.out.println(pred.test(student.getHeight()));// 消费消息Consumer<String> consumer = System.out::println;consumer.accept("我命由我不由天");// 转换功能Function<Student, String> function = Student::getName;String name = function.apply(student);System.out.println(name);// 生产消息Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());System.out.println(supplier.get());// 一元操作UnaryOperator<Boolean> unaryOperator = u -> !u;Boolean apply = unaryOperator.apply(false);System.out.println(apply);// 二元操作BinaryOperator<Integer> binaryOperator = (x, y) -> x * y + 2;Integer binary = binaryOperator.apply(5, 15);System.out.println(binary);}}
【 Student::getName;】这种操作被称之为方法引用
自定义函数式接口
/*** 测试自定义lambda函数式接口** @author zukxu* CreteTime 2021/7/17 0017 00:34*/public class TestCustomFunc {public static void main(String[] args) {testCustom(() -> "我是一个自定义函数式接口");}public static void testCustom(Worker worker) {System.out.println(worker.work());}public interface Worker {String work();}}
一、why?
函数式编程更多时候是一种编程的思维方式,是种方法论。函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做。说白了,函数式编程是基于某种语法或调用API去进行编程。
例如:
命令式编程
public static void main(String[] args) {int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7, 8};int min = Integer.MAX_VALUE;for (int num : nums) {if (num < min) {min = num;}}System.out.println(min);}
函数式编程:
public static void main(String[] args) {int[] nums = new int[]{1, 2, 3, 4, 5, 6, 7, 8};int min = IntStream.of(nums).min().getAsInt();System.out.println(min);}
二、lambda函数式接口
1.函数接口
接口只能有一个需要实现的方法,可以使用@FunctionalInterface 注解进行声明。如下:
@FunctionalInterfaceinterface Interface1 {int doubleNum(int i);}
使用lambda表达式进行获取相关实现实例:
public static void main(String[] args) {// 最常见的写法Interface1 i1 = (i) -> i * 2;Interface1 i2 = i -> i * 2;// 可以指定参数类型Interface1 i3 = (int i) -> i * 2;// 若有多行代码可以这么写Interface1 i4 = (int i) -> {System.out.println(i);return i * 2;};}
2.默认方法
比较重要的一个接口特性是接口的默认方法,用于提供默认实现。默认方法和普通实现类的方法一样,可以使用this等关键字
@FunctionalInterfaceinterface Interface1 {int doubleNum(int i);default int add(int x, int y) {return x + y;}}
之所以说默认方法这个特性比较重要,是因为我们借助这个特性可以在以前所编写的一些接口上提供默认实现,并且不会影响任何的实现类以及既有的代码。例如我们最熟悉的List接口,在JDK1.2以来List接口就没有改动过任何代码,到了1.8之后才使用这个新特性增加了一些默认实现。这是因为如果没有默认方法的特性的话,修改接口代码带来的影响是巨大的,而有了默认方法后,增加默认实现可以不影响任何的代码。
3.当接口多重继承时
当接口多重继承时,可能会发生默认方法覆盖的问题,这时可以去指定使用哪一个接口的默认方法实现,如下示例:
@FunctionalInterfaceinterface Interface1 {int doubleNum(int i);default int add(int x, int y) {return x + y;}}@FunctionalInterfaceinterface Interface2 {int doubleNum(int i);default int add(int x, int y) {return x + y;}}@FunctionalInterfaceinterface Interface3 extends Interface1, Interface2 {@Overridedefault int add(int x, int y) {// 指定使用哪一个接口的默认方法实现return Interface1.super.add(x, y);}}
