Java8之后,推出了一个新特性:Lambda表达式
作用:可以以更简洁的方式创建匿名内部类
语法:
(参数列表)->{
方法体
}
这里引入了一个新的符号:->
,我们称之为箭头符号
由上述语法可以看出,Lambda表达式由箭头符号分为了两部分:
注意事项:Lambda表达式只能用于接口中只有一个抽象方法的情境中
这里我们先用一个我们已经学习过的知识复习一下我们简单的Lambda表达式
// 创建一个文件对象
File dir = new File(".");
// 获取当前目录下的所有子项
File[] files = dir.listFiles(); // [.idea,src,target,pom.xml]
/*
listFiles() 存在一个重载的方法 -> File[] listFiles(FileFilter filter)
这个方法能筛选出符合过滤条件的所有子项
该方法要求传入一个文件过滤器,然后仅将满足过滤器要求的所有子项进行返回。
*/
File[] filter = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isDirectory();
}
}); // [.idea,src,target]
// lambda写法
// 1)忽略接口名和方法名
File[] filter1 = dir.listFiles((File file) -> {
return file.isDirectory();
});
// 2)参数类型可以忽略。如果方法只有一个参数时,那么"()"也可以忽略。
File[] filter2 = dir.listFiles(file -> {
return file.isDirectory();
});
// 3)如果方法体只有一句代码,那么可以将方法体"{}"忽略,如果含有return则return要一同忽略
File[] filter3 = dir.listFiles(file -> file.isDirectory());
for (File file : filter) {
System.out.println(file.getName());
}
// 开启线程
new Thread(new Runnable() {
// 定义线程任务
@Override
public void run() {
System.out.println("线程的名字 : " + Thread.currentThread().getName());
}
}).start();
// Lambda表达式写法
// 无参的情况下,()保留
new Thread(() -> System.out.println("Lambda表达式线程的名字 : " + Thread.currentThread().getName())).start();
要求 | 语法 | |
---|---|---|
无参无返回值 | 只有一条语句,{}可以省略 | ()->System.out.println("xx"); |
有多条语句 | ()->{ System.out.println("xx"); System.out.println("xx"); } | |
有参无返回值 | 一个参数,参数()可以省略 | x->System.out.println("xx"); |
多个参数 | (x,y)->System.out.println("xx"); | |
无参有返回值 | 只有一条语句,return可以省略 | ()->xxxx; |
有参有返回值 | 只有一条语句,return可以省略 | x->(x,y)->xxxx; |
有多条语句,return不可以省略 | (x,y)->{ System.out.println("xx"); return xxxx; } |
注意事项:当一个接口中存在多个抽象方法时,如果使用Lambda表达式,并不能智能的匹配到对应的抽象方法,所以这里引入了函数式接口的概念
只包含一个抽象方法的接口,称为函数式接口。
通常我们会在函数式接口上使用 @FunctionalInterface
注解来标记它是一个函数式接口,使用了该注解标记的接口,会在编译期检查该接口是否是函数式接口,提醒开发者。(非强制性,不使用该注解标记,只要符合只包含一个抽象方法要求同样是函数式接口,但建议使用)
编译错误:
添加 @FunctionalInterface
注解,定义接口 SimpleAbstractMethodInterface
为函数式接口,但是由于接口中编写了两个抽象方法,导致在编译期检查时发生错误,起到了一个提醒的作用。