“Lambda ”这一篇搞定~

在正式开始之前,先用官方话术描述一下什么是Lambda表达式 ~Lambda 表达式是一种匿名函数,也可称为闭包,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。Lambda 表达式也是Java8中最值得学习的新特性之一。主要作用是:对接口进行非常简洁的实现,从而简化代码。

    注意在上述描述中有一个名词:“匿名函数”。那么什么是“匿名函数”呢?在了解这个概念之前我们要知道“什么是匿名内部类?”,这篇文章将一点点将“Lambda 表达式”说清楚、让每一位伙伴都对Java8的这一新特性熟悉、并进行使用~ LET'S GO

 一、什么是匿名内部类?

   关于内部类一共可以分为四种:“成员内部类”、“局部内部类”、“匿名内部类”、“静态内部类”,其中“匿名内部类”需要重点掌握,这里呢也介绍这一种,另外三种较为简单,了解即可。有兴趣的伙伴可以普及~

  匿名内部类:在类中定义一个没有名称只有类体的类,一般使用在抽象类和实现类(接口)中。

匿名内部类的定义格式:
接口名称 对象名 = new 接口名称() {
// 覆盖重写所有抽象方法
};

下面分别从这两种形式去认识匿名内部类,废话不说,直接上代码!!

抽象类:
package com.example.rabbitmq_demo.niebulei;

/**
 * @ClaseName: Animal$
 * @Description:匿名内部类-抽象
 * @Author: wuhs
 * @Date: 2023/7/26$ 17:43$
 *
 */
public abstract class Animal {
    //    抽象方法
    public abstract void eat();

    public static void main(String[] args) {
        //正常调用方式,先创建实现类,然后调用方法
        Animal cat = new Cat();
        Animal dog = new Dog();
        dog.eat();

        // 下列方式是使用匿名内部类调用
        // Animal animal = new Animal() ;错误的,抽象类不能直接实例化,要加上方法体
        Animal a = new Animal() {
            //实现里面的抽象方法
            @Override
            public void eat() {
                System.out.println("女朋友,吃吃喝喝逛逛gai");
            }
        };
        a.eat();
    }
}


//创建实现类
class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

//创建实现类
class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
接口实现类:
package com.example.rabbitmq_demo.niebulei;

public interface Car {
    //接口中创建两个方法
    void run();
    void stop();



    public static void main(String[] args) {
    //    使用匿名内部类实现接口的方法
    //    示例:去创建一个五菱宏光,并实现里面的方法
        Car wlhgCar = new Car() {
            @Override
            public void run() {
                System.out.println("五菱宏光MINI,跑起来YYDS");
            }
            @Override
            public void stop() {
                System.out.println("五菱宏光MINI,立马停了下来");
            }
        };
        wlhgCar.run();
        wlhgCar.stop();
    }
}

//通常接口中的实现方式,需要创建一个类,然后实现接口,重写接口里面的方法
class BMcar implements Car{
    @Override
    public void run() {

    }
    @Override
    public void stop() {

    }
}

  通过上面的两个实例,会对“匿名内部类”有个大概认识。而接下来还需要对一个名词有所了解--“函数式接口,因为lambda 表达式只能实现函数式接口。那么什么是“函数式接口”?

函数式接口:一个接口中,要求实现类必须实现的抽象方法,有且只有一个!这样的接口,就是函数式接口。具体看代码!

//这个接口中,有且只有一个方法,是实现类必须实现的,因此是一个函数式接口
interface Test1 {
	void test();
}
//这个接口中,实现类必须要实现的方法,有两个!因此不是一个函数式接口
interface Test2{
	void test1();
    void test2();
}
//这个接口中,实现类必须要实现的方法,有零个!因此不是一个函数式接口
interface Test3 {

}
//这个接口中,虽然没有定义任何的方法,但是可以从父接口中继承到一个抽象方法的。是一个函数式接口
interface Test4 extends Test1 {

}
//这个接口,虽然里面定义了两个方法,但是defualt方法子类不是必须实现的。
//因此,实现类实现这个接口的时候,必须实现的方法只有一个!是一个函数式接口。
interface Test5 {
	void test5();
	default void test(){}
}
//这个接口中的toString方法,是object类中定义的方法。
//此时,实现类在实现接口的时候,toString可以不重写的!因为可以从父类Object中继承到!
//此时,实现类在实现接口的时候,有且只有一个方法是必须要重写的。是一个函数式接口!
interface Test6 {
	void test6();
	String toString();
}

知道这些之后,下面进入主题---->

二、Lambda表达式的语法

lambda表达式,其实本质来讲,就是一个匿名函数。因此在写lambda表达式的时候,不需要关心方法名是什么。

实际上,我们在写lambda表达式的时候,也不需要关系返回值类型。

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

lambda 表达式的基础语法:

(参数) -> {
    方法体
};


1、参数部分: 方法的参数列表,要求和是实现的接口给中的方法参数部分一致,包括参数的数量和类型。

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

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

 在这里介绍一个注解:@FunctionalInterface,是一个注解,用在接口之前,判断这个接口是否是一个函数式接口。如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。

三、Lambda表达式的使用(实现函数式接口)

 1、无返回值、无参数的函数式接口

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    void getName();
}

// 通常实现方法
class LambdaTest01Impl implements LambdaTest01{
    @Override
    public void getName() {
        System.out.println("这是接口的通常实现方式");
    }
}

//接口的Lambda实现类
class mainTest{
    public static void main(String[] args) {
        LambdaTest01 lambdaTest01  = ()->{
            System.out.println("这是接口的Lambda实现方式");
        };
        lambdaTest01.getName();
    }
}

 2、无返回值、有一个参数的函数式接口

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    void getName(String name);
}

// 通常实现方法
class LambdaTest01Impl implements LambdaTest01{
    @Override
    public void getName(String name) {
        System.out.println("这是接口的通常实现方式"+name);
    }
}

//接口的Lambda实现类
class mainTest{
    public static void main(String[] args) {
        /*写法一:
        LambdaTest01 lambdaTest01  = (name)->{
            System.out.println("这是接口的Lambda实现方式--》"+name);
        };*/

        // 写法二:参数的()可以省略
        LambdaTest01 lambdaTest01  = name->{
            System.out.println("这是接口的Lambda实现方式--》"+name);
        };
        
        lambdaTest01.getName("张三");
    }
}

 3、无返回值、有一个以上参数的函数式接口

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    void getName(String name,int age);
}

// 通常实现方法
class LambdaTest01Impl implements LambdaTest01{
    @Override
    public void getName(String name,int age) {
        System.out.println("这是接口的通常实现方式");
    }
}

//接口的Lambda实现类
class mainTest{
    public static void main(String[] args) {
        LambdaTest01 lambdaTest01  = (String name,int age)->{
            System.out.println("这是接口的Lambda实现方式--》"+name+age);
        };

        lambdaTest01.getName("张三",11);
    }
}

 注意:lambda表达式参数的类型可以省略,当参数大于一个的时候,要嘛每个参数都带上参数类型,要嘛就一个都不要加,不然会报错!!

 4、有返回值、有一个参数的函数式接口

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    String getName(String name);
}

// 通常实现方法
class LambdaTest01Impl implements LambdaTest01{
    @Override
    public String getName(String name) {
        System.out.println("这是接口的通常实现方式");
        return name;
    }
}

//接口的Lambda实现类
class mainTest{
    public static void main(String[] args) {
        LambdaTest01 lambdaTest01  = name->{
            System.out.println("这是接口的Lambda实现方式--》"+name);
            return name;
        };

        String getName = lambdaTest01.getName("张三");
        System.out.println(getName);
    }
}

 前面我们提到Lambda表达式作用就是对接口进行非常简洁的实现,从而简化代码。所以在函数式接口中不建议使用较为复杂的代码逻辑,如果有复杂的逻辑要处理,可以将其进行剥离,在Lambda表达式中进行调用,如以下代码所示~

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    String getName(String name);
}

// 通常实现方法
class LambdaTest01Impl implements LambdaTest01 {
    @Override
    public String getName(String name) {
        System.out.println("这是接口的通常实现方式");
        return name;
    }
}

//创建一个方法代替一段复杂的代码逻辑
class Cult {
    int a1 = 13;
    int a2 = 31;

    @Override
    public String toString() {
        return "Cult{" +
                "a1=" + a1 +
                ", a2=" + a2 +
                '}';
    }
}

//接口的Lambda实现类
class mainTest {
    public static void main(String[] args) {
        LambdaTest01 lambdaTest01 = name -> {
            //其他复杂的逻辑
            Cult cult = new Cult();
            System.out.println(cult.toString());

            System.out.println("这是接口的Lambda实现方式--》" + name);
            return name;
        };

        String getName = lambdaTest01.getName("张三");
        System.out.println(getName);
    }
}

四、Lambda表达式的使用(静态方法的引用)

  • 语法:

    • 类::静态方法
  • 注意事项:

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

 具体操作看下面实例~~~

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    String getName(String name);
}

class person {
    public static String getn(String name) {
        return name;
    }
}

//接口的Lambda实现类
class mainTest {
    public static void main(String[] args) {
         /**
          LambdaTest01的接口方法getName的实现,调用的person类的getn()方法
          需要注意的是:
          1、在引用的方法后面,不要添加小括号
          2、引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致
          */
        LambdaTest01 getn = person::getn;
        String xgsm = getn.getName("暇光曙墨");
        System.out.println(xgsm);
    }
}

 五、Lambda表达式的使用(非静态方法的引用)

 非静态方法的引用和静态方法的引用大同小异,语法如下:

  • 对象::非静态方法

需要的注意的事项仍与引用静态方法一致,具体操作看一下代码实例~

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    String getName(String name);
}

class PerClass {
    public  String getn(String name) {
        return name;
    }
}

//接口的Lambda实现类
class mainTest {
    public static void main(String[] args) {
         /**
          LambdaTest01的接口方法getName的实现,调用的person类的getn()方法
          需要注意的是:
          1、在引用的方法后面,不要添加小括号
          2、引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致
          */
        LambdaTest01 getn = new PerClass()::getn;
        System.out.println(getn.getName("暇光曙墨"));
    }
}

 六、Lambda表达式的使用(构造方法的引用)

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

语法:
类名::new
 

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

 具体使用方式看如下示例~~

/**
 * @ClaseName: LambdaTest$
 * @Description:
 * @Author: wuhs
 * @Date: 2023/7/28$ 14:07$
 */
//构建一个函数式接口
@FunctionalInterface
public interface LambdaTest01 {
    //有且仅有一个方法、并带有一个参数
    PerClass getName(String name);
}

class PerClass {
    int age;
    String name;

    //无参构造方法
    public PerClass() {
        System.out.println("这是无参构造方法");
    }

    //全参构造方法
    public PerClass(int age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("这是全参构造方法");
    }

    // 只有一个参数的构造方法
    public PerClass(int age) {
        this.age = age;
        System.out.println("这是只有一个参数的构造方法,参数是年龄:" + age);

    }
    //只有一个参数的构造方法---本次示例演示的类型
    public PerClass(String name) {
        this.name = name;
        System.out.println("这是只有一个参数的构造方法,参数是姓名:" + name);

    }
}

//接口的Lambda实现类
class mainTest {
    public static void main(String[] args) {
        //一个参数、参数是String的
        LambdaTest01 getn = PerClass::new;
        getn.getName("暇光曙墨");
    }
}

以上是本篇文章的全部内容,旨在快速入门~希望能帮到诸位

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暇光曙墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值