最新消息:

java 8新特性——Lambda表达式

JAVA 大步 935浏览 0评论

java 8中提供了lambda表达式。

1.Lambda表达式

  • lambda表达式是匿名函数(anonymous functions)
  • 是对那些内部只含有一个方法的接口的实例化
  • 省去啰嗦的类的声明语句

1.1实例:

实现一个接口
在java 8之前,我们实现一个接口,如下:

然后在新线程中开启:

使用内部类
将上面的改成内部类实现,可以省略部分声明类的代码:

使用匿名内部类
如果还想省,可以使用匿名内部类

使用Lambda表达式
使用lambda表达式,可以更简洁:

2.在什么地方使用lambda表达式

lambda表达式只能用在给变量赋值,而这个变量的类型必须是函数式接口(functional interface)

更多详情,见lambda translation

2.1函数式接口(functional interface)

  • 一个函数式接口只有一个抽象方法。
  • java运行时中的函数式接口有:Runnable,Callable,Comparator,TimeTask
  • java 8 中称这种为“Single Abstract Method”(SAM)类型

见java 8中的Runnable接口的声明:

2.2 Lambda表达式的语法

以Runnable接口为例子:

lamba

lambda表达式分为两部分
1.第一个部分是()括号内的,其实就是函数式接口里的抽象方法的方法签名。而Runnable接口的run()方法刚好没有参数,所以是空的。(注意:如果方法的参数只有一个,那么可以省略括号)
2.第二个部分是箭头后面的语句,那个是抽象方法的具体实现。如果有多条语句,需要用花括号括起来

下面是多条语句:

3. 自定义函数式接口

定义一个函数式接口,必须用@FunctionalInterface注解标记,如下:

用lambda表达式实现这个接口:

结果:
result:5

4.使用java 8内置的函数式接口

4.1 Runnable接口

未使用lambda:

使用lambda后:

4.2 Comparator接口

未使用Lambda之前:

使用lambda后:

4.3 使用lambda遍历集合

未使用lambda之前:

因为List类实现了Iterable接口,所以ArrayList自然也实现了Iterable接口的foreach方法,ArrayList的foreach源代码如下:

其中的Consumer接口是个函数式接口,源码如下:

所以,这里我们foreach中Comsumer接口中的accept抽象方法可以用lambda表达式来替代,如下:

4.4 使用Predicte接口过滤集合

将Predicte作为匿名类来过滤集合

Person.java:

将Predicate作为内部类:

对Predicate接口使用lambda表达式

5.使用方法引用(method reference)

方法引用(method reference) 可以将某个方法当作参数传递给另外一个方法。

实例:
在Person.java中添加一个静态方法compareAges,如下:

通过方法引用来将其作为参数传递给Collections.sort()方法:

结果:
Mary (30)
Joe (48)
Mike (73)

我们也可以将compareAges()方法放到StaticMethodReference类中,而且去掉它的static,作为一个实例方法,如下:

6.接口的中的默认方法(default method)

java 8 中接口可以定义静态方法和默认方法(default method),先说默认方法:

使用场景:

在java 8以前,如果一个接口要是需要添加方法,那么所有已经实现了这个接口的类就必须全部修改。为了避免这个问题,在java 8中,我们可以使用默认方法来实现添加方法,同时又不会影响已经实现类。因为其他的实现类可以重写这个默认方法,也可以不重写。

 

实例:

PersonInterface接口,其中定义了一个默认方法:

Person类,实现了PersonInterface接口:

调用接口的默认方法:

 

6.1 陷阱

结果:
Hello
分析:
如果一个类从它的父类继承一个方法,又从它的父接口那里继承一个方法签名相同的方法。此时,这个类会继承这个父类的方法,而忽略掉这个父接口的方法。
当一个类通过类继承的方式继承的方法不可用的时候,则一个接口中与这个方法的签名相同的默认方法就会作为一个备用方法。

6.2 陷阱

有接口A,类B,A中定义的默认方法签名与B中的方法一样。类C继承了B,实现了A。则如何调用接口A中的默认方法?
方法如下:使用 InterfaceName.super.method()

demo2

 

 

6.3陷阱

当一个了实现一个有默认方法的接口时,可以不重写默认方法。但是,如果有两个接口的默认方法相同,而类C由同时implements这两个接口,则类C必须重写默认方法,否则编译错误。

运行:
编译报错。
解决办法:实现接口中的方法。如果要调用某个接口的方法,则需要显示的调用。

 

 

7.接口中的静态方法(static method)

接口中也可以定义静态方法,和在普通类中定义静态方法是一样的。

 

注意:接口中的静态方法不能与默认方法签名相同,否则编译错误

实例:

PersonInterface接口中定义了一个静态方法:

Person类,实现了PersonInterface:

调用接口的静态方法:

转载请注明:大步's Blog » java 8新特性——Lambda表达式

SiteMap