Lambda表达式是什么?
Lambda表达式也称为闭包,是Java 8 发布的新特性
Lambda允许把函数作为一个方法的参数(函数作为方法的参数传递进方法中)
为什么使用Lambda表达式?
避免匿名内部类定义过多,可以让代码简洁紧凑,留下核心逻辑。
Lambda表达式的格式:
格式:(形式参数) -> {代码块}
形式参数:如果代码有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
-> :由英文中划线和大于号组成,固定写法,代表指向动作
代码块:是我们具体要做的事情,也就是之前 方法体的内容
实例一:
Lambda表达式是 方法 在调用接口中抽象方法时 直接实现接口中的抽象方法(如下)
实例二:
抽象方法带参时Lambda表达式如何传参(如下)
Lambda表达式的使用前提:
有一个接口,接口中有且只有一个抽象方法。
Lambda表达式的省略模式:
省略规则:
1、参数类型可以省略,但是有多个参数的情况下,不能只省略一个参数类型(要么全省略、要么全不省略)。
useFun((s) -> { System.out.println(s);}); // 参数的类型可以省略
2、如果参数有且仅有一个,那么小括号可以省略。
useFun( s -> {System.out.println(s);}); // 单个参数可以省略括号
3、如果代码块的语句只有一条,可以省略大括号和分号,甚至是return。
useFun( s -> System.out.println(s)); // 代码块中单个语句可以省略大括号
Lambda表达式的注意事项:
1、使用Lambda表达式必须要有接口,并且要求接口中有且仅有一个抽象方法。
2、必须有上下文环境,才能推导出Lambda对应的接口。
例: 启动线程用Lambda
根据局部变量的赋值得知Lambda对应的接口:
Runnable r = () -> System.out.println(" Lambda表达式 "); 正确
根据调用方法的参数得知Lambda对应的接口:
new Thread(() -> System.out.println(" Lambda表达式 ")).start(); 正确
() -> System.out.println(" Lambda表达式 "); 错误
Lambda表达式和匿名内部类的区别:
所需类型不同:
匿名内部类:可以是接口,也可以是抽象类,还可以是具体类。
Lambda表达式:只能是接口。
使用限制不同:
匿名内部类:接口中可以有一个或多个抽象方法。
Lambda表达式:接口中只能有一个抽象方法。
实现原理不同:
匿名内部类:编译之后,产生一个单独的.class字节码文件。
Lambda表达式:编译之后,没有产生一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。
=========================================================================
方法引用:
方法引用符:
● :: 该符号为引用运算符,而它所在的表达式被称为方法引用。进一步简化一些使用了Lambda表达式的代码。
Lambda表达式:usePrintable( s -> System.out.println(s) );
分析:拿到参数 s 后通过Lambda表达式,传递给 System.out.println方法去处理。
方法引用:usePrintable(System.out :: println);
分析:直接使用System.out中的println方法来取代Lambda,代码更加简洁。
推导与省略:
1、如果使用Lambda,那么根据“ 可推导就是可省略 ”的原则,无需指定参数类型,也无需指定的重载形式,它们都将被自动推导。
2、如果使用方法引用,也是同样可根据上下文进行推导。
3、方法引用是Lambda的”孪生兄弟“。
Lambda表达式支持的方法引用:
常见的引用方式:
引用类方法:引用类的静态方法。
格式:类名::静态方法
范例:Integer::parseInt
引用对象的实例方法:引用类中的成员方法。
格式:对象::成员方法
范例:"HelloWorld" :: toUpperCase
引用类的实例方法:引用类中的成员方法。
格式:类名 :: 成员方法
范例:String :: substring
引用构造器: 引用构造方法。
格式:类名 :: new
范例:Student :: new