加个“星标”,每天上午 09:25,干货推送!
来源 csdn | 编程一只蝶
文章目录
一、Lambda表达式简介二、Lambda表达式语法三、函数引用1.静态方法引用2.非静态方法引用3.构造方法引用4.对象方法的特殊引用四、Lambda表达式需要注意的问题
一、Lambda表达式简介
Lambda表达式,是Java8的一个新特性,也是Java8中最值得学习的新特性之一。(另一个新特性是流式编程。)
Lambda表达式,从本质上讲是一个匿名方法。可以使用这个匿名方法,实现接口中的方法。功能:通常使用Lambda表达式,是为了简化接口实现的。关于接口实现可以有多种方式实现,例如:①设计接口的实现类、②使用匿名内部类。但是③使用lambda表达式,比这两种方式都简单。要求:lambda表达式,只能实现函数式接口:即一个接口中,要求实现类必须实现的抽象方法,有且只有一个。@FunctionalInterface注解 ,用在接口之前,用来判断接口是否是一个函数式接口。如果不是函数式接口会报错。功能类似于@Override。
二、Lambda表达式语法
lambda表达式本质上是一个匿名方法,因此再写lambda表达式时,不需要关心方法名是什么,也不需要关心返回值类型。只需要关心两部分:参数列表、方法体。
()参数部分:方法的参数列表,要求和实现的接口中的方法参数部分一致,包括参数的数量和类型。{}方法体部分:方法的实现部分,如果接口中定义的方法有返回值,则在实现时,注意返回值的返回。-> :分隔参数部分和方法体部分。Lambda表达式基础语法:(参数)->{ 方法体}
下面定义6种参数和返回值各不相同的函数式接口,分别使用lambda表达式对接口中的方法进行实现:
下面是针对上面6种函数式接口的lambda表达式实现。
/** * @Description: * @author Guoqianliang * @date 19:50 - 2021/2/15 */publicclassBasicSyntax{publicstaticvoidmain(String[] args){// 1.实现无参数,无返回值的函数式接口 NoneReturnNoneParameter lambda1 =()->{ System.out.println("这是无参,无返回值的方法");}; lambda1.test();// 2.实现一个参数,无返回值的函数式接口 NoneReturnSingleParameter lambda2 =(int a)->{ System.out.println("这是一个参数,无返回值的方法,参数a:"+ a);}; lambda2.test(10);// 3.实现多个参数,无返回值的函数式接口 NoneReturnMutipleParameter lambda3 =(int a,int b)->{ System.out.println("这是多个参数,无返回值的方法,参数a="+ a +",b="+ b);}; lambda3.test(10,20);// 4.实现无参数,有返回值有返回值的函数式接口 SingleReturnNoneParameter lambda4 =()->{ System.out.println("这是无参数,有返回值的方法,返回值是:");return10;}; System.out.println(lambda4.test());// 5.实现一个参数,有返回值的函数式接口 SingleReturnSingleParameter lambda5 =(int a)->{ System.out.println("这是一个参数,有返回值的方法,返回值是:");return a;}; System.out.println(lambda5.test(10));// 6.实现多个参数,有返回值的函数式接口 SingleReturnMutipleParameter lambda6 =(int a,int b)->{ System.out.println("这是多个参数,有返回值的方法,返回值是:");return a + b;}; System.out.println(lambda6.test(1,2));}}
语法精简进阶:
参数列表的参数类型可以省略。如果参数列表中的参数有且只有一个,可以省略小括号。如果方法体中只有一条语句,可以省略大括号。(注:如果这条语句是返回语句,省略了大括号后也要把return关键字省略)三、函数引用
lambda表达式是为了简化接口。在lambda表达式中,不应该出现比较复杂的逻辑。如果需要处理的逻辑比较复杂,一般情况会单独写一个方法。在lambda表达式中直接引用这个方法即可。即引用一个已经存在的方法,使其代替lambda表达式完成接口的实现。
1.静态方法引用
语法:类::静态方法在引用的方法后面,不要添加小括号。引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致。
/** * @Description: 方法引用 * @author Guoqianliang * @date 0:26 - 2021/2/16 */publicclassLambda1{privatestaticinterfaceCalculate{intcalculate(int a,int b);}privatestaticintcalculate(int x,int y){if(x > y){return x - y;}elseif(x < y){return y - x;}return x + y;}publicstaticvoidmain(String[] args){// 静态方法引用 Calculate calculate = Lambda1::calculate; System.out.println(calculate.calculate(10,20));}}2.非静态方法引用
语法:对象::非静态方法在引用的方法后面,不要添加小括号。引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致。
/** * @Description: 方法引用 * @author Guoqianliang * @date 0:26 - 2021/2/16 */publicclassLambda1{privatestaticinterfaceCalculate{intcalculate(int a,int b);}// 非静态方法privateintcalculate2(int a,int b){if(a != b){return a - b;}return a + b;}publicstaticvoidmain(String[] args){// 非静态方法引用 Calculate calculate2 =newLambda1()::calculate2; System.out.println(calculate2.calculate(10,20));}}3.构造方法引用
语法:类名::new可以通过接口中的方法的参数,区分引用不同的构造方法。如果某一个函数式接口中定义的方法,仅仅是为了得到一个类的对象。此时就可以使用构造方法的引用,简化这个方法的实现。
/** * @Description: 构造方法引用 * @author Guoqianliang * @date 11:20 - 2021/2/16 */publicclassLambda2{@FunctionalInterfaceprivateinterfaceGetPersonWithNoneParameter{ Person get();}@FunctionalInterfaceprivateinterfaceGetPersonWithSingleParameter{ Person get(String name);}@FunctionalInterfaceprivateinterfaceGetPersonWithMutipleParameter{ Person get(String name,int age);}privatestaticclassPerson{ String name;int age;publicPerson(){ System.out.println("Person类的无参构造方法执行了");}publicPerson(String name){this.name = name; System.out.println("Person类的有参构造方法执行了");}publicPerson(String name,int age){this.name = name;this.age = age; System.out.println("Person类的两个参数的构造方法执行了");}}publicstaticvoidmain(String[] args){// 1.使用lambda表达式,实现GetPersonWithNoneParameter接口 GetPersonWithNoneParameter getPerson = Person::new;// 2.使用lambda表达式,实现GetPersonWithSingleParameter接口 GetPersonWithSingleParameter getPerson2 = Person::new;// 3.使用lambda表达式,实现GetPersonWithMutipleParameter接口 GetPersonWithMutipleParameter getPerson3 = Person::new; System.out.println(getPerson.get()); System.out.println(getPerson2.get("树先生")); System.out.println(getPerson3.get("你好",23));}}4.对象方法的特殊引用
使用lambda表达式实现某些接口时,如果lambda表达式中包含了某一个对象,此时方法体中,直接使用这个对象调用它的某一个方法就可以完成整体的逻辑。
/** * @Description: 对象方法的特殊应用 * @author Guoqianliang * @date 11:54 - 2021/2/16 */publicclassLambda3{@FunctionalInterfaceprivateinterfaceMyInterface{// String get(Person person);voidset(Person person, String name);}privatestaticclassPerson{private String name;publicvoidsetName(String name){this.name = name;}public String getName(){return name;}}publicstaticvoidmain(String[] args){ Person p1 =newPerson(); p1.setName("小明");// 逻辑实现只是为了获取到对象的名字// MyInterface lambda2 = Person::getName;// System.out.println(lambda2.get(p1));// 逻辑实现只是为了给对象的某些属性进行赋值 MyInterface lambda1 =(x, n)-> x.setName(n); MyInterface lambda2 = Person::setName; lambda2.set(p1,"李华"); System.out.println(p1.getName());}}123456789101112131415161718192021222324252627282930313233343536373839四、Lambda表达式需要注意的问题
如果用到局部变量,默认会被声明为常量,不能发生值的改变。
/** * @Description: * @author Guoqianliang * @date 13:05 - 2021/2/16 */publicclassLambda4{publicstaticvoidmain(String[] args){// 1.定义一个局部变量int x =10;// 2.使用lambda表达式实现接口 LambdaTest lambda =()->{ System.out.println("x="+ x);};// 3. 无法修改常量x// x=20;}}@FunctionalInterfaceinterfaceLambdaTest{voidtest();}
end