Lambda表达式简介
什么是Lambda?
Lambda是JAVA B添加的一个新的特性,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。说白了, Lambda就是一个匿名函数。
为什么要使用Lambda?
使用Lambda表达式可以对一个接口进行非常简洁的实现。
Lambda对接口的要求?
虽然可以使用Lambda表达式对某些接口进行简单的实现,但是并不是所有的接口都可以用Lambda表达式来实现。要求接口中定义的必须要实现的抽象方法只能是一个.eg:函数式接口
在JAVA8对接口加了一个新的特性: default.
函数式接口:
由@FunctionalInterface修饰,接口中的抽象方法有且仅有只有一个.
lambda 表达式的语法格式如下
(形参列表) -> 返回值 或(形参列表) ->{ 代码块}
以下是lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
Lambda 表达式实例
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
Lambda语法精简
- 参数类型:由于在接口的抽象方法中定义了参数的数目和类型,所以在Lambda表达式中,参数类型可以省略。备注如果需要省略参数类型,则每个参数的类型都要省略。(int a,int b)不可以省略成(a,int )
eg:
LambdaTest lambdaTest=(int a, int b)->{
System.out.println("hello world");
//可以是省略成
LambdaTest lambdaTest=( a, b)->{
System.out.println("hello world");};
2.参数小括号:如果参数列表中,参数的数量只有一个,
此时小括号可以省略。
LambdaTest lambdaTest=(int a)->{
System.out.println("hello world");};
//可以是省略成
LambdaTest lambdaTest=int a ->{
System.out.println("hello world");};
//也可以省略参数类型和括号
LambdaTest lambdaTest=a->{
System.out.println("hello world");};
- 方法大括号:如果方法中只有一条语句,此时大括号可以省略
//可以省略成
LambdaTest lambdaTest=a->System.out.println("hello world");
- 如果方法体中唯一的一条语句是一个返回语句,则在省略大括号的同时也省略return
LambdaTest lambdaTest=(a,b)->{return a+b }
//可以写成
LambdaTest lambdaTest=(a,b)-> a+b ;
//以下写法会报错
LambdaTest lambdaTest=(a,b)->return a+b ;
Lambda表达式进阶之函数引用:
方法引用的提出: 由于如果存在一种情况,我们新建了多个接口的实现对象,其方法都是相同的,但是如果方法需要修改,那么修改的复杂度就随着对象数量的上升而上升。
方法引用的定义: 快速将一个Lambda表达式的实现指向一个已经写好的方法
方法引用可以看作是lambda表达式的特殊形式,或者称之为语法糖。一般方法已经存在才可以使用方法引用,而方法若未存在,则只能使用lambda表达式。
可以快速的将一个Lambda的方法实现指向一个已经实现的方法。
语法:方法的隶属者::方法名
ublic class Demo1 {
public static void main(String[] args) {
LambdaExpression lambdaExpression1 = a -> change(a);
LambdaExpression lambdaExpression2 = Demo1::change;
}
private static int change(int a){
return a*2;
}
}
普通方法在Lambda表达式中的调用
public class Syntax3 {
public static void main(String[] args) {
/**
*方法引用:可以快速将一个Lambda表达式的实现指向一个已经写好的方法
*语法:方法的隶属者,静态方法隶属者为类,非静态方法的隶属者是对象
* 即:“方法的隶属者:方法名”
* 注意事项:
* 1.被引用的方法的参数数量以及类型一定要和接口中的方法参数数目一致
* 2.被引用的方法的返回值一定要和接口中的方法返回值一致
*
*
* 假如我们在程序中对于某个接口方法需要调用许多次,那么用以下的方法创建对象,来调用方法就是不太好的
* 缺点:如果将来要对方法进行改变,那么所有用Lambda表达式定义的对象都要更改,这在设计模式上就是有问题的;
* */
LambdaSingleReturnSingleParameter lambda1 = a -> a * 2;
LambdaSingleReturnSingleParameter lambda2 = a -> a * 2;
/**
* 我们一般是写一个通用的方法,并将其引用至Lambda表达式中
*
* */
LambdaSingleReturnSingleParameter lambda3 = a -> change(a);//在Lambda表达式中使用一般方法的调用方式
LambdaSingleReturnSingleParameter lambda4 = Syntax3::change;//在Lambda表达式种使用方法引用(方法隶属于类)
System.out.println(lambda4.test(2));
Syntax3 syntax3 = new Syntax3();//非静态方法需要对象才能被调用
LambdaSingleReturnSingleParameter lambda5 = syntax3::change2;//在Lambda表达式种使用方法引用(方法隶属于对象)
LambdaSingleReturnMultipleParameter lambda6 = syntax3::change3;//多参数的引用方法使用
}
private static int change(int a) {
return a * 2;
}
private int change2(int a) {
return a * 2;
}
}
private int change3(int a, int b) {
return a * 2 + b * 3;
}
构造方法在Lambda表达式中的调用
public class Person {
public String name;
public int age;
public Person() {
System.out.println("Person类的无参构造方法执行了");//语句用于判断无参构造器是否执行了
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("方法的有参构造方法执行了");//语句用于判断有参构造器是否执行了
}
}
Lambda表达式中引用构造方法的样例:
public class Syntax4 {
public static void main(String[] args) {
PersonCreater person = () -> new Person();
/**构造方法的引用
* 有参和无参构造器的调用区别在于所定义的接口中构造方法的参数区别
*/
PersonCreater creater1 = Person::new;
//无参方法
Person person1 = creater1.getPerson();
//有参方法
PersonCreater2 creater2=Person::new;
//再来传参
Person person2 = creater2.getPerson("Fisherman",18 );
}
}
//需求为:一个返回一个Person类的接口
interface PersonCreater {
Person getPerson();
}
interface PersonCreater2 {
Person getPerson(String name, int age);
}