Java8引入的lambda表达式
Java 8 引入的功能中,最让人期盼的是 lambda 表达式。lambda 表达式以字面量的形式把
少量代码直接写在程序中,而且让 Java 编程更符合函数式风格。
其实,lambda 表达式的很多功能都能使用嵌套类型通过回调和处理程序等模式实现,但使
用的句法总是非常冗长,尤其是,就算只需要在回调中编写一行代码,也要完整定义一个
新类型。
lambda 表达式其实就是没有名称的函数,在 Java 中可以把它当成一个值。Java 不允许
脱离类的概念运行方法,所以 lambda 表达式是在某个类中定义的匿名方法(开发者可
能不知道具体是哪个类) 。
lambda表达式的基本语法为:
(paramlist) -> {statements}
参数列表 方法主体
下面是一个十分传统的简单示例:
输出结果如下:
以下为简单的lambda表达式示例:
interface Lambda {
public int exp1();
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 1.() -> 588 不需要参数 返回的结果为588
Lambda lb = () -> 588;
System.out.println(lb.exp1());
}
}
interface Lambda {
public int exp1(int x);
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 1.(x) -> 2 * x 一个参数返回他本身的两倍
Lambda lb = (x) -> 2 * x;
System.out.println(lb.exp1(68));
}
}
interface Lambda {
public int exp1(int x, int y);
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 1.(x,y) -> x + y 两个参数返回它们的和
Lambda lb = (x,y) -> x + y;
System.out.println(lb.exp1(68,32));
}
}
interface Lambda {
public String exp1(String str);
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 1.(x) -> "head" + x + "tail" 一个参数在字符串两头分别加上了head 和 tail
Lambda lb = (x) -> "head" + x + "tail";
System.out.println(lb.exp1("abc"));
}
}
interface Lambda {
public void exp1(String str,String str1,String str2);
}
public class LambdaDemo1 {
public static void main(String[] args) {
// 1.(x,y,z) -> System.out.println(x + "-->" + y + "--->" + z);
// 三个参数直接输出这三个字符串的组合
Lambda lb = (x,y,z) -> System.out.println(x + "-->" + y + "--->" + z);;
lb.exp1("I", "Love", "You");
}
}
lambda 表达式当成值使用时,会根据要存储的变量类型,自动转换为相应的对象。自动转
换和类型推导是 Java 实现 lambda 表达式的基础。但是,这要求正确地理解 Java 的整个类
型系统。
上面这些简单的示例,相信大家都应该明天了,如果上面的表示你还不能看懂,那么我再用一个示例你就应该能明白其基本法则了。
例如, java.io.File 类的 list() 方法。这个方法列出一个目录中的文件,但在返回列
表之前,要把每个文件的名称传给 FilenameFilter 对象,而这个对象必须由你提供。
FilenameFilter 对象用于接受或拒绝各个文件。
使用匿名类可以按照如下的方式定义一个 FilenameFilter 类,只列出文件名以 .java 结尾
的文件:
以上方式是我们常用的一种过滤方式获取文件中后缀名以java结尾的文件,这样写下来有时候会觉得代码有点多余,那么这里lambda表达式就更好的体现了他的便捷性
下面为lambada表达式获取文件中后缀名为java结尾的文件:
相信到这里,大家已经明白了lambda表达式带来的语法方便吧。这种句法能通过一种十分紧凑的方式表
示简单的方法,而且能很大程度上避免使用匿名类。组成方法的各个部分,lambda 表达式几乎都有,不过
显然,lambda 表达式没有名称。其实,有些开发者喜欢把 lambda 表达式当成“匿名方法” 。
转换lambda表达式
javac 遇到 lambda 表达式时会把它解释为一个方法的主体,这个方法具有特定的签名。不过,是哪个方法呢?
为了解决这个问题, javac 会查看周围的代码。lambda 表达式必须满足以下条件才算是合法的 Java 代码:
lambda 表达式必须出现在期望使用接口类型实例的地方;
期望使用的接口类型必须只有一个强制方法;
这个强制方法的签名要完全匹配 lambda 表达式。
如果满足上述条件,编译器会创建一个类型,实现期望使用的接口,然后把 lambda 表达式的主体当作强制方法的实现。
说得稍微复杂一点儿,这么做是为了保持 Java 类型系统的名义(基于名称)纯粹性。也就是说,lambda 表达式会被转换成正确接口类型的实例。
有些开发者还喜欢使用“单一抽象方法” (Single Abstract Method,SAM)类型这个术语表示
lambda 表达式转换得到的接口类型。这表明,若想在 lambda 表达式机制中使用某个接口,这个接口必须只有一个非默认方法。
简单的lambda表达式就介绍到这里,Java 8 引入 lambda 表达式的一个主要原因是大幅修改集合 API,
让 Java 开发者使用更现代化的编程风格。关于集合中使用lambda的介绍,后面再完善介绍下