Java的Lambda表达式和函数接口
Java的Lambda表达式和函数接口
下面主要将四个方面,并会给出具体的例子
- 函数接口
- lambda表达式
- 使用Lambda表达式作为函数接口参数
- 使用方法引用或构造器作为函数接口参数
1.函数接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
如定义了一个函数式接口如下:
@FunctionalInterface //该注解只是显示的标注了接口用是一个函数接口,并强制编译器进行更严格的检查,如果不是就会报错。但也如果保证该接口是一个函数式接口也也可以不加该注解。
interface GreetingService
{
void sayMessage(String message);
}
函数式接口可以对现有的函数友好地支持 lambda。
2.lambda表达式
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
组成格式即:
- (数据类型 参数名,数据类型 参数名…):用来向表达式主体传递接口方法需要的参数。在编写Lambda表达式时**,可以省略参数的数据类型,后面的表达式主体会自动进行校对和匹配**。同时,如果只有参数,则可以省略括号()
- -> : 表示lambda表达式箭牌,用来指向参数数据指向,不能省略,且必须用英文符号。
- {表达式主体}:由单个表达式或语句块组成的主体,本质就是接口中抽象方法的具体实现。如果表达式主体只有一条语句,那么可以省略包含主体的大括号。另外,在lambda表达式主体中允许有返回值,当只有一条return语句时,也可以省略return关键字 。
lambda表达式多用于实现函数接口作为方法参数。
3.使用Lambda表达式实现函数接口
举一个例子
package learn;
import java.util.*;
interface FucInterface {
public void print(String s);
}
public class Learn {
public static void main(String[] args) {
String s="ZZZzzzzZZZZZzzzzzzZZZZZ";
ceshi(s, _s-> System.out.println("Lambda s:"+_s) );
}
static public void ceshi(String s,FucInterface fuc) {
fuc.print(s);
}
//Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ
}
在这里首先定义了一个函数接口FucInterface,接下来又定义了一个函数ceshi,改函数接受一个String参数和一个实现FucInterface 接口的对象,最后调用对象的print方法。
我们可以在使用ceshi函数时 FucInterface 接口的对象用lambda表达式代替,因为 FucInterface 接口是一个函数接口,这样lambda表达式会自动替换该接口的函数,所以在调用该接口的函数时,就会相当于调用该lambda表达式。
4.方法引用和构造器来作为函数接口参数
引用传智播客出品的java基础入门
使用方法引用和构造器,这两种形式可以进一个简化Lambda表达式的书写,其本质都是对Lambda表达式的主体部分已存在的方法进行直接引用,主要区别就是对普通方法和构造器方法的引用而已。
上面的黑体字是核心,表示使用这两种方法,其根本还是会被转化为Lambda表达式函数体调用。
种类 | Lambda表达式示例 | 对应的引用示例 |
---|---|---|
类名引用普通方法 | (x,y,…)-> 对象名x.类普通方法(y…) | 类名::类普通方法名 |
类名引用静态方法 | (x,y,…)-> 类名.类静态方法(x,y…) | 类名::类静态方法名 |
对象名引用方法 | (x,y,…)-> 对象名.(x,y…) | 对象名::实例方法名 |
构造器引用 | (x,y,…)-> new 类名(x,y,…) | 类名::new |
其中第1种不容易理解,不过这里略过了O(∩_∩)O.
这里只阐述最常用的 类名引用静态方法,其他的不再描述
就以上面的例子为例,还可以这样写
package learn;
import java.util.*;
interface FucInterface {
public void print(String s);
}
class Ces{
static void output(String _s) {
System.out.println("s:"+_s);
}
}
public class Learn {
public static void main(String[] args) {
String s="ZZZzzzzZZZZZzzzzzzZZZZZ";
ceshi(s, _s-> System.out.println("Lambda s:"+_s) );
System.out.println("============================");
ceshi(s,_s->Ces.output(_s) );
System.out.println("============================");
ceshi(s,Ces::output);
}
static public void ceshi(String s,FucInterface fuc) {
fuc.print(s);
}
//Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ
}
/* 输出: Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ ============================ s:ZZZzzzzZZZZZzzzzzzZZZZZ ============================ s:ZZZzzzzZZZZZzzzzzzZZZZZ */
其中第二种调用的方式与第三种等效。
这个过程可以理解为直接将Ces类的output函数 替换成接口函数的那个函数了。