函数式接口概述
函数式接口:只有一个抽象方法的接口
有且仅有一个抽象方法的接口,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式。Lambda就是Java中函数式编程的体现。
函数式接口特点和约束
1.单一抽象方法:函数式接口只有一个未实现的抽象方法。
2.Lambda表达式目标类型:函数式接口可以作为Lambda表达式的目标类型,即Lambda表达式可以作为函数式接口的实现。
3.默认方法和静态方法:函数式接口可以包含默认方法和静态方法,但它们不影响接口的函数式特性。
4.标记注解:函数式接口可以使用@FunctionalInterface注解进行标记,该注解用于提醒编译器检查接口是否符合函数式接口的定义。
函数式接口分类
主要分布在 java.util.function 包下,常见的 4大原始函数 接口为:Function (函数型接口)、Predicate
(断定型接口)、Consumer (消费型接口)、Supplier (供给型接口)
@FunctionalInterface注解
Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解放在接口上,表示此接口是一个函数式接口。并且提示编译器去检查接口是否仅包含一个抽象方法,即,是否符合函数式编程的定义。
1.Function接口
有一个输入参数,一个输出
函数式接口不是 有且只有一个方法 吗?为什么存在default 和 static的方法
static:static方法可以被继承,但是不能被覆盖
default:java8在接口中新增default方法,是为了在现有的类库中新增功能而不影响其实现类,也就是说,该接口的实现类可以直接调用default方法,而不需要实现它!
Function<String,String> function = new Function<String, String>() {
@Override
public String apply(String str) {
return str;
}
};
System.out.println(function.apply("abc"));
等同于: Function<String,String> function = (str)->{return str;};
2.predict
test方法传入一个参数,返回一个boolean值
示例:
public static void main(String[] args) {
Predicate<Integer> predicate =new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return 0 != integer;
}
};
System.out.println(predicate.test(0));
}
3.Consumer
accept方法传入一个参数,但是不返回值
示例:
public static void main(String[] args) {
// 该接口一般用于数组或集合的遍历输出
consumerTest(new Consumer<String>() { // 使用匿名内部类创建创建对象,并实现Consumer接口
@Override
public void accept(String str) {
//将字符串转为小写
System.out.println(str.toLowerCase());
//将字符串转为大写
System.out.println(str.toUpperCase(Locale.ROOT));
}
});
}
/**
* 一个字符串转成大写和小写的字符串
* @param consumer 输入的参数
*/
public static void consumerTest(Consumer<String> consumer) {
String str = "Hello World!";
consumer.accept(str);
}
andThen方法
先执行accept(t),再执行after方法
示例:
Consumer<Integer> consumer = x -> System.out.println(x);
Consumer<Integer> consumer2 = x -> {
int a = x + 4;
System.out.println(a);
};
consumer.andThen(consumer2).accept(10);
4.Supplier:生产型接口
示例:
public static void main(String[] args) {
supplierTest(new Supplier<Integer>() { // 使用匿名内部类创建对象,并实现Supplier接口
@Override
public Integer get() { // 重写Supplier接口中的get方法
int[] arrays = new int[]{1, 3, 6, 5, 9, 2, 234, 16, 0};
Arrays.sort(arrays);
return arrays[arrays.length - 1];
}
});
}
/**
* 获取数组元素最大值
* @param supplier 提供者
*/
public static void supplierTest(Supplier<Integer> supplier) {
Integer max = supplier.get();
System.out.println(max);
}
Lambda表达式与函数式接口的关系
1.Lambda表达式可以替代使用匿名内部类的方式来实现函数式接口中的抽象方法
2.Lambda表达式可以通过函数式接口来实现,即可以将Lambda表达式赋给函数式接口类型的变量或作为参数传递给接受函数式接口作为参数的方法。
Lambda表达式和函数式接口的关系可以简单总结为:Lambda表达式是实现函数式接口的一种方式