什么是Lambda表达式?
Lambda表达式是Java8的新特性,Java8允许程序通过该表达式来代替功能接口。从而达到简化冗余代码,提高开发效率的效果,也可以说是函数式接口实例化的替代方案。
编译器在编译使用Lambda表达式的类时,会在该类中创建一个匿名内部类。并在内部类中定义一个静态方法。
为什么要使用Lambda表达式?
举个简单的例子。假设我们现在需要启动一个线程去完成一个无需返回值的任务。
通常我们会创建一个Runnable接口的匿名内部类对象来指定任务内容,再将其交给一个线程来启动。
Idea代码为:
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("需要执行的代码");
}
});
thread.start();
}
}
控制台的输出为:
我们不妨分析一下,我们最初的想法只是启动一个线程去完成一个无返回值任务。
但想要完成这个任务Thread类又需要我们传递一个Runnable对象。
而Runnable又是一个接口,为了避免定义实现类,我们又使用了匿名内部类的方式创建该对象。
为了创建该对象我们又必须重写其抽象方法,且方法名称、方法参数、方法返回值类型不得不重写一遍,且不能写错。
实际上,只有run方法方法体中的代码才是我们想执行的操作。
其他代码都是为了让run方法方法体中的代码能成功被Thread类获取,而编写的。
我们真的希望创建一个Runnable对象吗?不。我们只是为了完成这件事情而不得不创建一个对象。
我们希望的只是将run方法的方法体传递给Thread类,让其知晓它应该做什么。
创建Runnable对象只是受限于面向对象语法而不得不采取的一种手段方式。
那,有没有更加简单的办法?
而这个问题的解决方案,就是Lambda表达式
如何使用Lambda表达式
1.标准语法:
([parameter, ...])->{
}
([parameter, ...])代表的是接口中抽象方法的形参列表,
{}代表的则是该抽象方法的方法体。
将之前的例子使用Lambda表达式书写
Idea代码为:
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(()->{
System.out.println("需要执行的代码");
});
thread.start();
}
}
控制台输出为:
Thread构造参数中的“()”就代表run方法的形参列表,而->所指向的就是run方法的方法体。
这段代码和刚才的执行效果是完全一样的,可以在1.8或更高的编译级别下通过。
从代码的语义中可以看出:我们创建了一个线程,而线程任务的内容以一种更加简洁的形式被指定。
2.省略写法
1.当方法形参个数为一个时,"()"可省略。
2.当方法体执行语句只有一句时"{} return ;"都可省略
将之前的例子使用Lambda表达式的省略写法书写
Idea代码:
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(()->System.out.print("需要执行的代码"));
thread.start();
}
}
控制台输出:
值得注意的是无论是标准写法还是省略写法,Lambda表达式只对函数式接口或SAM接口有效
延迟加载
在程序运行时,都会用到日志,而日志打印或多或少都会出现某些资源浪费的情况,例如打印错误信息时,需要根据错误的级别可打印的日志也不相同。
未使用Lambda的代码
public static void main(String[] args) {
int code = 0;
String message1 = "出现了";
String message2 = "exception";
logPrint(code, message1+message2);
}
/**
* 打印日志
* @param code 错误级别 0代表无错误 1代表出现错误
* @param message 打印信息
*/
public static void logPrint(int code, String message){
if(code != 0){
System.out.println(message);
}
}
从上面代码可以发现,code的值无论为何值,程序都会有一次字符串拼接的操作
下面我们来看使用Lambda表达式后的代码。
/**
* 自定义的打印接口
*/
@FunctionalInterface
interface MessagePrint{
/**
* 打印日志
* @param code 错误级别 0代表无错误 1代表出现错误
*/
void logPrint(int code);
}
public static void main(String[] args) {
int code = 1;
String message1 = "出现了";
String message2 = "exception";
logPrint(code, (x)-> {
if(x==1){
System.out.println(message1+message2);
}
});
}
public static void logPrint(int code, MessagePrint mt){
mt.logPrint(code);
}
以上代码当且仅当code为1时,才会进行字符串拼接的操作,这就是Lambda的又一特性——延迟加载(懒加载)