Lambda表达式
Lambda表达式
1. Lambda表达式简介
java 8提出了Lambda表达式专门用于实现只有一个抽象方法接口,相比较传统通过类实现接口的方式更简洁、实现更方便
2. Lambda表达式语法
2.1 Lambda标准语法
以下是标准语法格式
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}
举例:接口定义抽象方法形式主要有以下三种:无返回值无参数、无返回值有参数、有返回值和参数,接下来将对三种情况,采用Lambda表达式实现接口进行举例:
(1)无返回值无参数
//接口:
@FunctionalInterface // 函数事接口声明,这类接口只能有一个抽象方法
public interface ITest {
void run();
}
//调用:
public class LambdaDemo {
public static void main(String[] args) {
ITest itest = ()-> {System.out.println("Itest");};
itest.run(); // 输出结果:Itest
}
}
(2)无返回值有参数
//接口:
@FunctionalInterface // 函数事接口声明,这类接口只能有一个抽象方法
public interface ITest2 {
void printInt(int i);
}
//调用:
public class LambdaDemo {
public static void main(String[] args) {
ITest2 itest2 = (int i)-> {System.out.println(i);};
itest2.printInt(100); // 输出:100
}
}
(3)有返回值有参数
// 接口:
@FunctionalInterface // 函数事接口声明,这类接口只能有一个抽象方法
public interface ITest3 {
String get(int i);
}
// 调用:
public class LambdaDemo {
public static void main(String[] args) {
ITest3 itest3 = (int i)-> {return "str"+i;};
System.out.println(itest3.get(1000)); // 输出:str1000
}
}
2.2 Lambda省略语法
(1)参数类型可以省略:
public class LambdaDemo {
public static void main(String[] args) {
ITest2 itest2 = (i)-> {System.out.println(i);};
itest2.printInt(100); // 输出:100
}
}
(2)如果只有一个参数可以省略括号:
public class LambdaDemo {
public static void main(String[] args) {
ITest2 itest2 = i-> {System.out.println(i);};
itest2.printInt(100); // 输出:100
}
}
(3) 如果没有返回值并且只有一句语句可以省略花括号
public class LambdaDemo {
public static void main(String[] args) {
ITest2 itest2 = i-> System.out.println(i);
itest2.printInt(100); // 输出:100
}
}
3. Lambda方法引用
3.1 方法引用介绍
方法引用就是通过实例对象或类的方法来覆盖函数式接口的抽象方法,来实现一个函数式接口的实例,例如:
例子1:
Timer timer = new Timer(1000,event -> System.out.println(event));
timer.start();
// 方法引用
Timer timer2 = new Timer(1000,System.out::println); // System.out是PrintStream类的实例对象 println是实例方法
timer2.start();
JOptionPane.showMessageDialog(null, "是否退出");
System.exit(0);
例子2:
Runnable runnable = System.out::println; // 用System.out实例对象println方法覆盖Runnable的run抽象方法
runnable.run(); // 输出一个空行
3.2 方法引用示例
方法引用主要有三种情况:
(1)object::instanceMethod
(2)Class::instanceMethod
(3)Class::staticMethod
方法引用 | 等价lambda表达式 | 说明 |
---|---|---|
separator::equals | x -> separator.equals(x) | 包含对象和实例方法的表达式,lambda参数作为这个方法的显示参数传入 |
String::trim | x -> x.trim | 包含类和实例方法(无参数)的表达式,lambda参数会变成隐式参数传入 |
String::concat | (x,y) -> x.concat(y) | 包含类和实例方法(有参数)的表达式,lambda参数1会变成隐式参数传入,参数二作为显示参数传入 |
Integer::sum | (x,y) -> Integer::sum(x,y) | 包含类和静态方法的表达式,lambda所有参数会直接传递给这个静态方法 |
4 Lambda构造器引用
4.1 简介
Lambda构造器引用是用来替代在Lambda表达式只是通过类构造方法返回对象使用场景:
// Person对象
public class Person {
private String name;
private int age;
public Person(){
System.out.println("无参构造方法调用了");
}
public Person(String name,int age){
this.name = name;
this.age = age;
System.out.println("有参构造方法调用了");
}
}
// 构造器引用:
public class LambdaDemo2 {
public static void main(String[] args) {
// lambda表达式实现
PersonCreate personCreate = () -> new Person();
personCreate.getPerson(); // 输出:无参构造方法调用了
// 采用构造方法引用
PersonCreate personCreate2 = Person::new; // 与第一种方式等价
personCreate2.getPerson(); // 输出:无参构造方法调用了
// lambda表达式实现
PersonCreateByPam personCreateByPam2 = (name,age) -> new Person(name,age);
personCreateByPam2.getPerson("k",100); // 输出:有参构造方法调用了
// 采用构造方法引用
PersonCreateByPam personCreateByPam = Person::new; // 与上面Lambda表达式等价
personCreateByPam.getPerson("k",100); // 输出:有参构造方法调用了
}
}
interface PersonCreate{
Person getPerson(); // 定义返回Person对象抽象方法
}
interface PersonCreateByPam{
Person getPerson(String name,int age); // 定义返回Person对象抽象方法
}
5 Lambda闭包
闭包就是能够读取其他函数内部变量的函数,Lambda表达式就可以实现:
public class LambdaDemo2 {
public static void main(String[] args) {
// 闭包调用:不使用闭包情况下closureF函数的局部变量num在该函数执行完后
// 就销毁了,但通过Lambda表达式将局部变量保持了下来,以至于可以在其他函数种访问
Supplier<Integer> closureF = closureF();
Integer integer = closureF.get();
System.out.println(integer);
}
public static Supplier<Integer> closureF(){
int num = 100; // 使用闭包后,编译器会将它变成 final int num = 100
return () -> num;
}
}