java Lambda表达式 用法

1.什么是Lambda表达式

Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。

Lambda表达式的使用场景:用以简化接口实现

参考例子:

定义接口

@FunctionalInterface
public interface Test { public void test(); }

  

接口的实现

@RequestMapping(value = "/test", method= RequestMethod.GET)
    public void MyTest(){
        Test test =()->{
            System.out.println("test");
        };
        test.test();
    }

  

Lambda表达式对接口的要求

 lambda表达式,只能实现函数式接口(如果说,⼀个接口中,要求实现类必须实现的抽象方法,有且只有⼀个!这样的接口,就是函数式接口。@FunctionalInterface),并不是所有的接口都可以使用lambda表达式来简洁实现的。 lambda表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候,lambda表达式都是不适用

 

Lambda表达式的基础语法

写lambda表达式的时候,只需要关注两部分内容即可:参数列表和方法体

方法体部分 : 方法的实现部分,如果接口中定义的方法有返回值,则在实现的时候,注意返回值的返回。

-> : 分隔参数部分和方法体部分。

lambda表达式的基础语法:
(参数1,参数2,…) -> {
    方法体
};

  

代码示例

public interface TestArgs {
    public String myTest(String test_str);
}

  

    @RequestMapping(value = "/testArgs", method= RequestMethod.GET)
    public void MyTestArgs(){
        TestArgs testArgs =(test_str)->{
            System.out.println(test_str);
            return test_str;
        };
        String test_str=testArgs.myTest("hello");
        System.out.println(test_str);
    }

  

代码精简

如果方法的参数列表中的参数数量 有且只有⼀个,此时,参数列表的小括号是可以省略不写的。

注意事项:

  • 只有当参数的数量是⼀个的时候, 多了、少了都不能省略。
  • 省略掉小括号的同时, 必须要省略参数的类型
Test test = name -> {
            System.out.println(name+"test");
        };
        test.test("小新");

  

当⼀个方法体中的逻辑,有且只有⼀句的情况下,⼤括号可以省略

Test test = name -> System.out.println(name+"test");
        test.test("小新");

  

如果⼀个方法中唯⼀的⼀条语句是⼀个返回语句, 此时在省略掉大括号的同时, 也必须省略掉return。

Test test = (a,b) -> a+b;

  

1.静态方法的引用
语法:类::静态方法

注意事项:

在引用的方法后面,不要添加小括号。
引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的⼀致
package test;

/**
* @author: Mercury
* Date: 2022/3/20
* Time: 18:17
* Description:lambda表达式静态方法引用
* Version:1.0
*/
public class Test05 {
public static void main(String[] args) {
//实现多个参数,一个返回值的接口
//对一个静态方法的引用,语法:类::静态方法
Test1 test1 = Calculator::calculate;
System.out.println(test1.test(4,5));
}
}

class Calculator{
public static int calculate(int a,int b ){
// 稍微复杂的逻辑:计算a和b的差值的绝对值
if (a > b) {
return a - b;
}
return b - a;
}
}

interface Test1{
int test(int a,int b);
}
2.非静态方法的引用
语法:对象::非静态方法

注意事项:

在引用的方法后⾯,不要添加小括号。
引用的这个方法, 参数(数量、类型) 和 返回值, 必须要跟接口中定义的⼀致。
package test;

/**
* @author: Mercury
* Date: 2022/3/21
* Time: 8:14
* Description:lambda表达式对非静态方法的引用
* Version:1.0
*/
public class Test06 {
public static void main(String[] args) {
//对非静态方法的引用,需要使用对象来完成
Test2 test2 = new Calculator()::calculate;
System.out.println(test2.calculate(2, 3));
}
private static class Calculator{
public int calculate(int a, int b) {
return a > b ? a - b : b - a;
}
}
}
interface Test2{
int calculate(int a,int b);
}
3.构造方法的引用
使用场景

如果某⼀个函数式接口中定义的方法,仅仅是为了得到⼀个类的对象。此时我们就可以使用构造方法的引用,简化这个方法的实现。

语法:类名::new

注意事项:可以通过接口中的方法的参数, 区分引用不同的构造方法。

package com.cq.test;

/**
* @author: Mercury
* Date: 2022/4/27
* Time: 10:31
* Description:lambda构造方法的引用
* Version:1.0
*/
public class Test {
private static class Dog{
String name;
int age;
//无参构造
public Dog(){
System.out.println("一个Dog对象通过无参构造被实例化了");
}
//有参构造
public Dog(String name,int age){
System.out.println("一个Dog对象通过有参构造被实例化了");
this.name = name;
this.age = age;
}
}
//定义一个函数式接口,用以获取无参的对象
@FunctionalInterface
private interface GetDog{
//若此方法仅仅是为了获得一个Dog对象,而且通过无参构造去获取一个Dog对象作为返回值
Dog test();
}

//定义一个函数式接口,用以获取有参的对象
@FunctionalInterface
private interface GetDogWithParameter{
//若此方法仅仅是为了获得一个Dog对象,而且通过有参构造去获取一个Dog对象作为返回值
Dog test(String name,int age);
}

// 测试
public static void main(String[] args) {
//lambda表达式实现接口
GetDog lm = Dog::new; //引用到Dog类中的无参构造方法,获取到一个Dog对象
Dog dog = lm.test();
System.out.println("修狗的名字:"+dog.name+" 修狗的年龄:"+dog.age); //修狗的名字:null 修狗的年龄:0
GetDogWithParameter lm2 = Dog::new;//引用到Dog类中的有参构造,来获取一个Dog对象
Dog dog1 = lm2.test("萨摩耶",2);
System.out.println("修狗的名字:"+dog1.name+" 修狗的年龄:"+dog1.age);//修狗的名字:萨摩耶 修狗的年龄:2

}
}

四、Lambda表达式需要注意的问题
这⾥类似于局部内部类、匿名内部类,依然存在闭包的问题。

如果在lambda表达式中,使用到了局部变量,那么这个局部变量会被隐式的声明为 final。是⼀个常量,不能修改值。

posted @ 2022-11-30 16:55  妇愁者纞萌  阅读(79)  评论(0编辑  收藏  举报