Lambda表达式
1、Lambada表达式概述
Lambda 是一个匿名函数,我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
写Lambda表达式的场景:
1. 能够使用 Lambda 表达式的一个重要依据是必须有相应的函数接口。所谓函数接口,是指内部有且仅有一个抽象方法的接口。
2. Lambda 表达式的另一个依据是类型推断机制。在上下文信息足够的情况下,编译器可以推断出参数列表的类型,而不需要显式指名。
2、Lambada基本语法
<1>Lambda表达式基本语法:
Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为->,该操作符被称为Lambda 操作符或箭头操作符。
它将Lambda 分为两个部分:
左侧:指定了Lambda 表达式需要的所有参数(对应接口中形参)
右侧:指定了Lambda 体,即Lambda 表达式要执行的功能。(方法体,可以推断返回值类型)
<2>Lambda表达式根据使用方式分为6类:
1. 无参数,无返回值
2. 有一个参数,无返回值
3. 若只有一个参数,小括号可以省略不写
4. 有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
5. 若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
6. Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
格式1:无参数,无返回值
基本语句格式
() -> {
执行语句
}
格式2:有一个参数,无返回值
基本语句格式
(变量名) -> {
执行语句
}
格式3:若只有一个参数,小括号可以省略不写
基本语句格式
变量名 -> {
执行语句
}
格式4:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
基本语句格式
(变量名1, 变量名2) -> {
执行语句;
return xxx;
}
格式5:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
基本语句格式
(变量名1, 变量名2) -> 要返回的结果;
格式6:类型推断(一般不这样使用)
基本语句格式
([类型] 变量名1, [类型] 变量名2) -> 要返回的结果;
3、Java内置函数接口
Predicate<T> 断言型接口
接口类型:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Function<T,R> 函数型接口
接口类型:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Supplier<T> 供给型接口
接口类型:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Consumer<T> 消费型接口
接口类型:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
4、Lambda用法再简洁之方法引用
1、对象的引用 :: 实例方法名
当我们要执行的表达式是调用某个对象的方法,并且这个方法的参数列表和接口里抽象函数的参数列表一一对应时,我们就可以采用引用对象的方法的格式。
假如 Lambda 表达式符合如下格式:
([变量1, 变量2, ...]) -> 对象引用.方法名([变量1, 变量2, ...])
我们可以简写成如下格式:
对象引用::方法名
2、类 :: 静态方法名
当我们要执行的表达式是调用某个类的静态方法,并且这个静态方法的参数列表和接口里抽象函数的参数列表一一对应时,我们可以采用引用静态方法的格式。
假如 Lambda 表达式符合如下格式:
([变量1, 变量2, ...]) -> 类名.静态方法名([变量1, 变量2, ...])
我们可以简写成如下格式:
类名::静态方法名
注意这里静态方法名后面不需要加括号,也不用加参数,因为编译器都可以推断出来。
3、类 :: 实例方法名
假如我们的 Lambda 表达式符合如下格式:
(变量1[, 变量2, ...]) -> 变量1.实例方法([变量2, ...])
那么我们的代码就可以简写成:
变量1对应的类名::实例方法名
若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
4、构造方法引用 ClassName::new
当我们要执行的表达式是新建一个对象,并且这个对象的构造方法的参数列表和接口里函数的参数列表一一对应时,我们就可以采用「引用构造方法」的格式。
假如我们的 Lambda 表达式符合如下格式:
([变量1, 变量2, ...]) -> new 类名([变量1, 变量2, ...])
我们就可以简写成如下格式:
类名::new
Function<String, Employee> fun = Employee::new;
System.out.println(fun.apply("xiaohu"));
5、数组引用
假如我们的 Lambda 表达式符合如下格式:
(变量) -> new 元素类型[变量]
我们就可以简写成如下格式:
元素类型[] :: new
6、误区:Lambda 表达式底层Lambda 表达式被封装成了主类的一个私有方法,并通过 invokedynamic 指令进行调用,并且书写 Lambda 表达式不会产生新的类。所以不能单纯的理解Lambda表达式和匿名内部类的实现原理是一样的,但是可以理解为简化匿名内部类的写法。
7、小结:
优点:
可以减少代码的书写,减少匿名内部类的创建,节省内存占用。
使用时不用去记忆所使用的接口和抽象函数。
缺点:
易读性较差,阅读代码的人需要熟悉 Lambda 表达式和抽象函数中参数的类型。
不方便进行调试。
5、新特性:枚举
JDK1.5之前使用枚举
/*
1. 创建枚举类的属性(成员遍历),必须是作为私有常量出现
2. 必须将构造方法私有化,这是为了保证类的对象是有限个的目的
3. 提供公共的静态的final方法给外界获取枚举类中多个对象
4. 提供公共的获取属性的方法
5. 重写toString()方法
*/
class Season{
//1. 创建枚举类的属性(成员遍历),必须是作为私有常量出现
private String name;
private String info;
//2. 必须将构造方法私有化,这是为了保证类的对象是有限个的目的
private Season(String name, String info){
this.name = name;
this.info = info;
}
//3. 提供公共的静态的final方法给外界获取枚举类中多个对象
public static final Season SPRING = new Season("春天","春暖花开");
public static final Season SUMMER = new Season("夏天","烈日炎炎");
public static final Season AUTUMN = new Season("秋天","秋高气爽");
public static final Season WINTER = new Season("冬天","白雪皑皑");
//4. 提供公共的获取属性的方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
}
public class SeasonDemo1 {
public static void main(String[] args) {
Season spring = Season.SPRING;
Season summer = Season.SUMMER;
}
}
JDK1.5之后使用枚举
/*
jdk1.5之后 java提供了一个关键字用于创建枚举类 enum
*/
enum Season2{
//jdk1.5之后必须将有限个对象放在enum枚举类第一个开头位置,多个对象之间使用逗号隔开
SPRING("春天","春暖花开"),
SUMMER("夏天","烈日炎炎"),
AUTUMN("秋天","秋高气爽"),
WINTER("冬天","白雪皑皑");
//1. 创建枚举类的属性(成员遍历),必须是作为私有常量出现
private String name;
private String info;
//2. 必须将构造方法私有化,这是为了保证类的对象是有限个的目的
private Season2(String name, String info){
this.name = name;
this.info = info;
}
//4. 提供公共的获取属性的方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
}
public class SeasonDemo2 {
public static void main(String[] args) {
Season2 spring = Season2.SPRING;
System.out.println(spring.getName());
System.out.println(spring.getInfo());
}
}
标签:info,name,String,概述,public,表达式,Lambda
From: https://www.cnblogs.com/snzjz/p/18475049