• 【Java】你会使用 Lambda 表达式吗?


    🔥一个人走得远了,就会忘记自己为了什么而出发,希望你可以不忘初心,不要随波逐流,一直走下去🎶
    🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
    🦄 本文由 程序喵正在路上 原创,CSDN首发!
    💖 系列专栏:Java入门
    🌠 首发时间:2022年7月21日
    ✅ 如果觉得博主的文章还不错的话,希望小伙伴们三连支持一下哦

    函数式编程思想概述

    在数学中,函数就是有输入量、输出量的一套计算方案,也就是 ”拿数据做操作“

    面向对象思想强调 ”必须通过对象的形式来做事情“

    函数式思想则尽量忽略面向对象的复杂语法:”强调做什么,而不是以什么形式去做“

    体验Lambda表达式

    在这里插入图片描述

    需求:启动一个线程,在控制台输出一句话:多线程程序启动了

    方式1:

    • 定义一个类 MyRunnable 实现 Runnable 接口,重写 run() 方法
    • 创建 MyRunnable 类的对象
    • 创建 Thread 类对象,把 MyRunnable 的对象作为构造函数传递
    • 启动线程
    //MyRunnable类
    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("多线程程序启动了");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    public class LambdaDemo {
        public static void main(String[] args) {
            //实现类的方式实现需求
    //        MyRunnable my = new MyRunnable();
    //        Thread t = new Thread(my);
    //        t.start();
    
            //匿名内部类的方式改进
    //        new Thread(new Runnable() {
    //            @Override
    //            public void run() {
    //                System.out.println("多线程程序启动了");
    //            }
    //        }).start();
    
            //Lambda表达式的方式改进
            new Thread(() -> {
                System.out.println("多线程程序启动了");
            }).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    方式2:

    • 匿名内部类的方式改进

    方式3:

    • Lambda 表达式的方式改进

    Lambda表达式的标准格式

    1. 匿名内部类中重写 run() 方法的代码分析

    new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("多线程程序启动了");
                }
            }).start();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 方法形式参数为空,说明调用方法时不需要传递参数
    • 方法返回值类型为 void,说明方法执行没有结果返回
    • 方法体中的内容,是我们具体要做的事情

    2. Lambda 表达式的代码分析

    new Thread(() -> {
                System.out.println("多线程程序启动了");
            }).start();
    
    • 1
    • 2
    • 3
    • ():里面没有内容,可以看成是方法形式参数为空
    • ->:用箭头指向后面要做的事情
    • { }:包含一段代码,我们称之为代码块,可以看成是方法体中的内容

    3. Lambda 表达式的格式

    • 格式:(形式参数) -> { 代码块 }
    • 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
    • ->:由英文中画线和大于符号组成,固定写法,代表指向动作
    • 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容

    Lambda表达式的练习

    1. Lambda 表达式的使用前提

    • 有一个接口
    • 接口中有且仅有一个抽象方法

    2. 练习1 (抽象方法无参无返回值)

    • 定义一个接口 (Eatable),里面定义一个抽象方法:void eat();
    • 定义一个测试类 (EatableDemo),在测试类中提供两个方法
      一个方法是:useEatable(Eatable e)
      一个方法是主方法,在主方法中调用 useEatable 方法
    public interface Eatable {
        void eat();
    }
    
    • 1
    • 2
    • 3
    //接口的实现类
    public class EatableImpl implements Eatable {
        @Override
        public void eat() {
            System.out.println("芝士,就是力量!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    //测试类
    public class EatableDemo {
        public static void main(String[] args) {
            //在主方法中调用 useEatable 方法
            Eatable e = new EatableImpl();
            useEatable(e);
    
            //匿名内部类
            useEatable(new Eatable() {
                @Override
                public void eat() {
                    System.out.println("芝士,就是力量!");
                }
            });
    
            //Lambda表达式
            useEatable(() -> {
                System.out.println("芝士,就是力量!");
            });
        }
    
        private static void useEatable(Eatable e) {
            e.eat();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    3. 练习2 (抽象方法带参无返回值)

    • 定义一个接口 (Flyable),里面定义一个抽象方法:void fly(String s);
    • 定义一个测试类 (FlyableDemo),在测试类中提供两个方法
      一个方法是:useFlyable(Flyable f)
      一个方法是主方法,在主方法中调用 useFlyable 方法
    public interface Flyable {
        void fly(String s);
    }
    
    • 1
    • 2
    • 3
    public class FlyableDemo {
        public static void main(String[] args) {
            //匿名内部类
            useFlyable(new Flyable() {
                @Override
                public void fly(String s) {
                    System.out.println(s);
                    System.out.println("匿名内部类");
                }
            });
    
            //Lambda表达式
            useFlyable(((String s) -> {
                System.out.println(s);
                System.out.println("Lambda表达式");
            }));
        }
    
        private static void useFlyable(Flyable f) {
            f.fly("风和日丽,晴空万里");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

    4. 练习3 (抽象方法带参带返回值)

    • 定义一个接口 (Addable),里面定义一个抽象方法:int add(int x, int y);
    • 定义一个测试类 (AddableDemo),在测试类中提供两个方法
      一个方法是:useAddable(Addable a)
      一个方法是主方法,在主方法中调用 useAddable 方法
    public interface Addable {
        int add(int x, int y);
    }
    
    • 1
    • 2
    • 3
    public class AddableDemo {
        public static void main(String[] args) {
            useAddable((int x, int y) -> {
                return x + y;
            });
        }
    
        private static void useAddable(Addable a) {
            int sum = a.add(10, 20);
            System.out.println(sum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    Lambda表达式的省略模式

    省略规则:

    • 参数类型可以省略,但是有多个参数的情况下,不能只省略一个
    • 如果参数有且仅有一个,那么小括号可以省略
    • 如果代码块的语句只有一条,可以省略大括号和分号,甚至是省略 return
    public class AddableDemo {
        public static void main(String[] args) {
            useAddable((int x, int y) -> {
                return x + y;
            });
    
            //参数的类型可以省略
            //但是有多个参数的情况下,不能只省略一个
            useAddable((x, y) -> {
                return x + y;
            });
    
            useFlyable((String s) -> {
                System.out.println(s);
            });
    
            //如果参数有且仅有一个,那么小括号也可以省略
            useFlyable(s -> {
                System.out.println(s);
            });
    
            //如果代码块的语句只有一条,可以省略大括号和分号
            useFlyable(s -> System.out.println(s));
    
            //如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
            useAddable(((x, y) -> x + y));
        }
    
        private static void useFlyable(Flyable f) {
            f.fly("风和日丽,晴空万里");
        }
    
        private static void useAddable(Addable a) {
            int sum = a.add(10, 20);
            System.out.println(sum);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    Lambda表达式的注意事项

    注意事项:

    • 使用 Lambda 表达式必须有接口,,并且要求接口中有且仅有一个抽象方法
    • 必须有上下文环境,才能推导出 Lambda 对应的接口
      根据局部变量的赋值得知 Lambda 对应的接口:Runnable = () -> System.out.println("Lambda表达式");
      根据调用方法的参数得知 Lambda 对应的接口:new Thread() -> System.out.prinln("Lambda表达式").start();
    public interface Inter {
        void show();
    }
    
    • 1
    • 2
    • 3
    public class LambdaDemo {
        public static void main(String[] args) {
            //使用Lambda表达式必须要有接口,并且要求接口中有且仅有一个抽象方法
            useInter(() -> System.out.println("好好学习,天天向上"));
    
            //必须有上下文环境,才能推导出Lambda对应的接口
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("匿名内部类");
                }
            }).start();
    
            new Thread(() -> System.out.println("Lambda表达式")).start();
        }
    
        private static void useInter(Inter i) {
            i.show();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    Lambda表达式和匿名内部类的区别

    所需类型不同

    • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
    • Lambda 表达式:只能是接口

    使用限制不同

    • 如果接口中有且仅有一个抽象方法,可以使用 Lambda 表达式,也可以使用匿名内部类
    • 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用 Lambda 表达式

    实现原理不同

    • 匿名内部类:编译之后,产生一个单独的 .class 字节码文件
    • Lambda 表达式:编译之后,没有一个单独的 .class 字节码文件,对应的字节码会在运行的时候动态生成
    public interface Inter {
        void show();
    }
    
    • 1
    • 2
    • 3
    public abstract class Animal {
        public abstract void method();
    }
    
    • 1
    • 2
    • 3
    public class Student {
        public void study() {
            System.out.println("爱生活,爱Java");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class LambdaDemo {
        public static void main(String[] args) {
            //匿名内部类
            useInter(new Inter() {
                @Override
                public void show() {
                    System.out.println("接口");
                }
            });
    
            useAnimal(new Animal() {
                @Override
                public void method() {
                    System.out.println("抽象类");
                }
            });
    
            useStudent(new Student() {
                @Override
                public void study() {
                    System.out.println("具体类");
                }
            });
    
            //Lambda表达式
            useInter(() -> System.out.println("接口"));
    //        useAnimal(() -> System.out.println("抽象类"));
    //        useStudent(() -> System.out.println("具体类"));
        }
    
        private static void useInter(Inter i) {
            i.show();
        }
    
        private static void useStudent(Student s) {
            s.study();
        }
    
        private static void useAnimal(Animal a) {
            a.method();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
  • 相关阅读:
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java智慧小区综合管理平台q1033
    Go学习笔记 -- 方法
    VsCode 配置java环境(详细教程)
    Stirling-PDF 安装和使用教程
    【.NET8】访问私有成员新姿势UnsafeAccessor(上)
    如何获取springboot中所有的bean
    基于虚幻引擎的AI训练合成数据生成
    Python数学建模-2.6文件操作
    发光太阳聚光器的蒙特卡洛光线追踪研究(Matlab代码实现)
    77.每日一练:迭代器遍历容器(牛客)
  • 原文地址:https://blog.csdn.net/weixin_62511863/article/details/125877659