函数式编程思想

Java从诞生之日起就一直倡导“一切皆对象”,在Java语言中面向对象(OOP)编程就是一切,但是随着Python和Scala等语言的崛起和新技术的挑战,Java也不得不做出调整以便支持更加广泛的技术要求,即Java语言不但支持OOP还支持OOF(面向函数编程)。

JDK1.8引入Lambda表达式之后,Java语言也开始支持函数式编程,但是Lambda表达式不是Java语言最早使用的,目前C++、C#、Python、Scala等语言都支持Lambda表示。

Lambda表达式是JDK1.8的一个新特性,可以取代大部分的匿名内部类,以便写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

  • 面向对象的思想

    • 做一件事情,找一个能解决这个事情的对象,然后调用对象的方法,最终完成事情。
  • 函数式编程思想

    • 只要能获得结果,谁去做的,怎么做的都不重要,重视的是结果,不重视实现过程。

JDK1.8中的Lambda表达式就是一个函数式接口的实例,这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以使用Lambda表达式来表示

对于函数式接口的理解

能够使用Lambda表达式的一个很重要的依据便是必须有相应的函数式接口,所谓的函数式接口,指的就是“一个接口中有且只能有一个抽象方法”。也就是说,如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。

如果我们在接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,也就是该接口中有且只能定义一个抽象方法,如果该接口中定义了多个或0个抽象方法,则程序编译时就会报错。

1
2
3
4
5
6
7
8
9
@FunctionalInterface
public interface Flyable {
// 在函数式接口中,我们有且只能定义一个抽象方法
void showFly();
// 但是,可以定义任意多个默认方法或静态方法
default void show() {
System.out.println("JDK1.8之后,接口还可以定义默认方法和静态方法");
}
}

另外,从某种意义上来说,只要你保证你的接口中有且只有一个抽象方法,则接口中没有使用 @FunctionalInterface 注解来标注,那么该接口也依旧属于函数式接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 没有使用@FunctionalInterface标注的接口
*/
public interface Flyable {
void showFly();
}
/**
* 测试类
*/
public class Test01 {
public static void main(String[] args) {
// 使用lambda表示来表示Flyable接口的实例
Flyable flyable = () -> {
System.out.println("小鸟自由自在的飞翔");
};
// 调用Flyable接口的实例的showFly()方法
flyable.showFly();
}
}

Lambda表达式与匿名内部类的区别:

  • 所需类型不同:

    • 匿名内部类:可以是接口,抽象类,具体类
    • Lambda表达式:只能是接口
  • 使用限制不同:

    • 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类。
    • 如果接口中有多个抽象方法,则就只能使用匿名内部类,而不能使用Lambda表达式。
  • 实现原理不同:

    • 匿名内部类:编译之后,会生成一个单独的.class字节码文件。
    • Lambda表达式:编译之后,没有生成一个单独的.class字节码文件。