本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!
作者| 慕课网精英讲师 ColorfulC
本篇文章我们将学习函数式接口相关的知识,包括什么是函数式接口,为什么需要函数式接口,如何自定义一个函数式接口,如何创建函数式接口的对象,以及一些 Java 内置的函数式接口的详细介绍等。1. 什么是函数式接口函数是接口(Functional Interface)的定义非常容易理解:只有一个抽象方法的接口,就是函数式接口。可以通过Lambda表达式来创建函数式接口的对象。我们来看一个在之前我们就经常使用的Runnable接口,Runnable接口就是一个函数式接口,下面的截图为 Java 源码:
我们看到Runnable接口中只包含一个抽象的run()方法,并且在接口上标注了一个@FuncationInterface注解,此注解就是 Java 8 新增的注解,用来标识一个函数式接口。2. 为什么需要函数式接口学习了这么久的 Java,我们对 Java 是纯种的面向对象的编程语言这一概念,可能有了一定的感触,在 Java 中,一切皆是对象。但是随着Python、scala等语言的兴起,函数式编程的概念得到开发者们的推崇,Java 不得不做出调整以支持更广泛的技术要求。在面向函数编程的语言中,Lambda表达式的类型就是函数,但是在 Java 中,Lambda表达式的类型是对象而不是函数,他们必须依赖于一种特别的对象类型——函数式接口。所以说,Java 中的Lambda表达式就是一个函数式接口的对象。我们之前使用匿名实现类表示的对象,都可以使用Lambda表达式来表示。3. 自定义函数式接口想要自定义一个函数式接口也非常简单,在接口上做两件事即可:定义一个抽象方法:注意,接口中只能有一个抽象方法;在接口上标记@FunctionalInterface注解:当然也可以不标记,但是如果错写了多个方法,编辑器就不能自动检测你定义的函数式接口是否有问题了,所以建议还是写上吧。/**
- 自定义函数式接口
- @author colorful@TaleLin
*/
@FunctionalInterface
public interface FunctionalInterfaceDemo {
void run();
}
代码块1234567891011由于标记了@FunctionalInterface注解,下面接口下包含两个抽象方法的这种错误写法,编译器就会给出提示:
4.创建函数式接口对象在上面,我们自定义了一个函数式接口,那么如何创建它的对象实例呢?我们可以使用匿名内部类来创建该接口的对象,实例代码如下:/**
- 测试创建函数式接口对象
- @author colorful@TaleLin
*/
public class Test {
public static void main(String[] args) {
// 使用匿名内部类方式创建函数式接口
FunctionalInterfaceDemo functionalInterfaceDemo = new FunctionalInterfaceDemo() {
@Override
public void run() {
System.out.println("匿名内部类方式创建函数式接口");
}
};
functionalInterfaceDemo.run();
}
}
代码块123456789101112131415161718运行结果:匿名内部类方式创建函数式接口
代码块1现在,我们学习了Lambda表达式,也可以使用Lambda表达式来创建,这种方法相较匿名内部类更加简洁,也更推荐这种做法。实例代码如下:/**
- 测试创建函数式接口对象
- @author colorful@TaleLin
*/
public class Test {
public static void main(String[] args) {
// 使用 Lambda 表达式方式创建函数式接口
FunctionalInterfaceDemo functionalInterfaceDemo = () -> System.out.println("Lambda 表达式方式创建函数式接口");
functionalInterfaceDemo.run();
}
}
代码块12345678910111213运行结果:Lambda 表达式方式创建函数式接口
代码块1当然,还有一种更笨的方法,写一个接口的实现类,通过实例化实现类来创建对象。由于比较简单,而且不符合我们学习函数式接口的初衷,这里就不再做实例演示了。5. 内置的函数式接口介绍通过上面一系列介绍和演示,相信对于函数式接口的概念和使用,你已经烂熟于心了。但是只知道这些还不够用,下面的内容才是本小节的重点,Java 中内置了丰富的函数式接口,位于java.util.function包下,学习这些函数式接口有助于我们理解 Java 函数式接口的真正用途和意义。Java 内置了 4 个核心函数式接口:Comsumer
/**
- Java 内置4大核心h函数式接口 —— 消费型接口
- Consumer
void accept(T t) - @author colorful@TaleLin
*/
public class FunctionalInterfaceDemo1 {
public static void main(String[] args) {
Consumer consumer = s -> System.out.println(s);
consumer.accept("只消费,不返回");
}
}
123456789101112131415运行结果:只消费,不返回
代码块1供给型接口使用实例:实例演示import java.util.function.Consumer;
import java.util.function.Supplier;
/**
- Java 内置4大核心h函数式接口 —— 供给型接口
- Supplier
T get() - @author colorful@TaleLin
*/
public class FunctionalInterfaceDemo2 {
public static void main(String[] args) {
Supplier supplier = () -> "只返回,不消费";
String s = supplier.get();
System.out.println(s);
}
}
1234567891011121314151617运行结果:只返回,不消费
代码块1下面我们使用断言型接口,来实现一个根据给定的规则,来过滤字符串列表的方法,实例如下:实例演示import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
- Java 内置4大核心函数式接口 —— 断言型接口
- Predicate
boolean test(T t) - @author colorful@TaleLin
*/
public class FunctionalInterfaceDemo3 {
/**
* 根据 Predicate 断言的结果,过滤 list 中的字符串
* @param list 待过滤字符串
* @param predicate 提供规则的接口实例
* @return 过滤后的列表
*/
public static List filterStringList(List list, Predicate predicate) {
// 过滤后的字符串列表
ArrayList arrayList = new ArrayList();
for (String string: list) {
if (predicate.test(string)) {
// 如果 test 是 true,则将元素加入到过滤后的列表中
arrayList.add(string);
}
}
return arrayList;
}
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
arrayList.add("Java");
arrayList.add("PHP");
arrayList.add("Python");
arrayList.add("JavaScript");
System.out.println("过滤前:");
System.out.println(arrayList);
List filterResult = filterStringList(arrayList, new Predicate() {
@Override
public boolean test(String s) {
// 返回字符串中是否包含 P
return s.contains("P");
}
});
System.out.println("过滤后:");
System.out.println(filterResult);
}
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950运行结果:过滤前:
[Java, PHP, Python, JavaScript]
过滤后:
[PHP, Python]
代码块1234当然,我们学习了Lambda表达式,在main()方法中就可以不再使用匿名内部类了,改写main()方法中调用filterStringList()方法的代码:List
代码块1上面的实例代码可能有些难以理解,跟着我的节奏来解读一下:先定义一个方法List
欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net