当前位置:

首页 > 编程开发 > Java如何使用Lambda表达式?

Java如何使用Lambda表达式?

一、Lambda表达式的简介Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。Lambda表达式的使用场景:用以简化接口实现。关于接口实现,可以有很多种方式来实现。例如:设计接口的实现类、使用匿名内部类。但是lambda表达式,比这两种方式都简单。packagetest;/***@author:Mercury*Date:2022/3/20*Time:17:48*Description:Lamb

本文目录

      一、Lambda表达式的简介

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

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

      关于接口实现,可以有很多种方式来实现。例如:设计接口的实现类、使用匿名内部类。 但是lambda表达式,比这两种方式都简单。

      package test;
      /**
       * @author: Mercury
       * Date: 2022/3/20
       * Time: 17:48
       * Description:Lambda表达式
       * Version:1.0
       */
      public class Test04 {
          public static void main(String[] args) {
              //使用lambda表达式实现接口
              Test test = () -> {
                  System.out.println("test");
              };
              test.test();
          }
      }
      interface Test{
          public void test();
      }

      二、Lambda表达式对接口的要求

      虽然说,lambda表达式可以在⼀定程度上简化接口的实现。但是,并不是所有的接口都可以使用lambda表达式来简洁实现的。

      lambda表达式毕竟只是⼀个匿名方法。当实现的接口中的方法过多或者多少的时候,lambda表达式都是不适用的。

      lambda表达式,只能实现函数式接口。

      1.函数式接口

      如果说,⼀个接口中,要求实现类必须实现的抽象方法,有且只有⼀个!这样的接口,就是函数式接口。

      代码如下(示例):

      //有且只有一个实现类必须要实现的抽象方法,所以是函数式接口
      interface Test{
          public void test();
      }

      2.@FunctionalInterface

      是⼀个注解,用在接口之前,判断这个接口是否是⼀个函数式接口。 如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。功能类似于 @Override。
      代码如下(示例):

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

      3.Lambda表达式的语法

      1.Lambda表达式的基础语法

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

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

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

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

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

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

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

      代码示例:

      package test;
      /**
       * @author: Mercury
       * Date: 2022/3/20
       * Time: 17:48
       * Description:Lambda表达式
       * Version:1.0
       */
      public class Test04 {
          public static void main(String[] args) {
              //使用lambda表达式实现接口
              //无参
      //        Test test = () -> {
      //            System.out.println("test");
      //        };
              //有参
      //        Test test = (name,age) -> {
      //            System.out.println(name+age+"岁了!");
      //        };
      //        test.test("小新",18);
              //有参+返回值
              Test test = (name,age)  -> {
                  System.out.println(name+age+"岁了!");
                  return age + 1;
              };
              int age = test.test("小新",18);
              System.out.println(age);
          }
      }
      //无参
      //interface Test{
      //    public void test();
      //}
      //有参 无返回值
      //interface Test{
      //    public void test(String name,int age);
      //}
      //有参 有返回值
      interface Test{
          public int test(String name,int age);
      }

      4.Lambda表达式的语法进阶

      参数部分的精简

      参数的类型

      由于在接口的方法中,已经定义了每⼀个参数的类型是什么。而且在使用lambda表达式实现接口的时候,必须要保证参数的数量和类 型需要和接口中的方法保持⼀致。因此,此时lambda表达式中的参数的类型可以省略不写。

      注意点:

      如果需要省略参数的类型,要保证:要省略, 每⼀个参数的类型都必须省略不写。绝对不能出现,有的参数类型省略了,有的参数类型没有省略。

              //有参+返回值
              Test test = (name,age)  -> {
                  System.out.println(name+age+"岁了!");
                  return age + 1;
              };
              int age = test.test("小新",18);
              System.out.println(age);

      参数的小括号

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

      注意事项:

      • 只有当参数的数量是⼀个的时候, 多了、少了都不能省略。

      • 省略掉小括号的同时, 必须要省略参数的类型

              //一个参数
              Test test = name -> {
                  System.out.println(name+"test");
              };
              test.test("小新");

      方法体部分的精简

      方法体⼤括号的精简

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

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

      return的精简

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

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

      三、函数引用

      lambda表达式是为了简化接口的实现的。在lambda表达式中,不应该出现比较复杂的逻辑。如果在lambda表达式中出现了过于复杂的逻辑,会对程序的可读性造成非常大的影响。如果在lambda表达式中需要处理的逻辑比较复杂,⼀般情况会单独的写⼀个方法。在lambda表达式中直接引用这个方法即可。

      函数引用:引用⼀个已经存在的方法,使其替代lambda表达式完成接口的实现

      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);
      }
      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。是⼀个常量,不能修改值。

      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发 Java
      相关文章 更多
      Java单元测试入门:使用JUnit 5编写第一个测试用例
      Java单元测试入门:使用JUnit 5编写第一个测试用例

      面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

      Java变量未初始化报错解析:局部变量与成员变量默认值差异
      Java变量未初始化报错解析:局部变量与成员变量默认值差异

      深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
      Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

      详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

      Java中final与static final常量的定义及初始化规则
      Java中final与static final常量的定义及初始化规则

      深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

      Java抽象方法与接口方法的区别及选型建议
      Java抽象方法与接口方法的区别及选型建议

      深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

      Java实现HTTP请求与JSON解析的完整代码示例
      Java实现HTTP请求与JSON解析的完整代码示例

      本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

      Java递归出现StackOverflowError的原因分析及栈空间优化方案
      Java递归出现StackOverflowError的原因分析及栈空间优化方案

      详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

      Java空指针异常(NPE)的代码排查与修复实例
      Java空指针异常(NPE)的代码排查与修复实例

      针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

      selenium上传文件教程本地文件路径设置方法
      selenium上传文件教程本地文件路径设置方法

      深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
      大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

      针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。