文档章节

Java8 lambda表达式、函数式接口、方法引用

aronykl
 aronykl
发布于 2017/08/12 15:15
字数 2694
阅读 308
收藏 5

一、函数式接口

什么是函数式接口呢?

函数式接口是Java8新增加的内容。如果一个接口只有一个抽象方法,那么该接口就是函数式接口。

我们知道,在Java8以前的版本,接口里面的方法都是抽象的方法,如果接口里只有一个抽象方法,那么该接口就是函数式接口。而在Java8中,接口中不仅仅只有抽象方法了。除了抽象方法,接口中还可以有静态方法和默认方法。例如Comparator接口,Java8以前只有一个 int compare(T o1, T o2); 方法,现在在里面增加了很多的静态方法和默认方法。
下面介绍下静态方法和默认方法,以及抽象方法。

  • 接口静态方法:需要在接口中对方法进行实现。跟普通类的静态方法一样,可以直接通过 接口名.方法名 对方法直接调用。
  • 接口默认方法:需要在接口中对方法进行实现,所有接口的实现类都默认继承该方法,当然子类也可以对该方法进行重写。
  • 接口抽象方法:即没有在接口中实现的方法。这里要注意,如果一个接口声明了java.lang.Object 中的public方法,那么,这些方法不会被算进接口抽象方法的归类。比如说toString方法。

我想Java8中对接口这么改造,一是处于对以前版本的兼容,二是为了Java8函数式编程的新的特性,三是接口中增加方法实现,让开发者可以直接调用,使编程更加的便捷简单。

FunctionalInterface注解

如果一个接口符合函数式接口的定义,那么我们就可以在该接口上面声明FunctionalInterface注解了,用来标示该接口是一个函数式接口,并按照函数式接口的规范在编译的时候对该接口进行检查。

如果我们在某个接口上声明了FunctionalInterface注解,那么编译器会按照函数式接口的定义来要求该接口。

如果某个接口只有一个抽象方法,但我们并没有给该接口声明FunctionalInterface注解,那么编译器依旧会将该接口看做是函数式接口。

二、Lambda表达式

上面介绍了Java8函数式接口,那么什么是Lambda表达式呢?Lambda表达式跟函数式接口又有什么关联呢?

在函数式编程语言当中,函数而不是对象,被当做一等公民对待。在将函数作为一等公民的编程语言中,Lambda表达式的类型是函数。但是在Java8中,有所不同。

在Java8中,Lambda表达式是对象,而不是函数,它们必须依附于一类特别的对象类型——函数式接口。

简单的说,在Java8中,Lambda表达式就是一个函数式接口的实例。这就是Lambda表达式和函数式接口的关系。也就是说,只要一个对象是函数式接口的实例,那么该对象就可以用Lambda表达式来表示。所以以前用匿名内部类表示的现在都可以用Lambda表达式来写。

Lambda表达式格式

(Object… args) -> expression
或者
(Object… args) -> {函数式接口抽象方法实现逻辑}

这里用一个Object的可变参数表示。()里面参数的个数,根据函数式接口里面抽象方法的参数个数来决定。

例如,Runnable接口的run方法没有参数,那就只要使用一个()来表示就好了,下面是代码实例:

Runnable thread = () -> System.out.println("hello world");

上面代码表示的意思是,定义一个线程,这个线程做的事情是打印”hello world”。上面的代码还可以看出,如果后面的逻辑只有一行,可以省略{}。也可以看出Lambda表达式其实就是函数式接口的一个实例。

如果函数式接口里面的抽象方法的参数有多个,那么Lambda表达式()里面的参数也要写多个,一般参数的类型可以根据抽象方法定义的参数类型推断出,因此参数前面的类型可以省略,如果不能推断出,参数前面需要加上