Java中Lambda表达式使用及详解



前言


一、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);
}

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;}}//定义一个函数式接口,用以获取无参的对象@FunctionalInterfaceprivate interface GetDog{//若此方法仅仅是为了获得一个Dog对象,而且通过无参构造去获取一个Dog对象作为返回值Dog test();}//定义一个函数式接口,用以获取有参的对象@FunctionalInterfaceprivate 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 修狗的年龄:0GetDogWithParameter lm2 = Dog::new;//引用到Dog类中的有参构造,来获取一个Dog对象Dog dog1 = lm2.test("萨摩耶",2);System.out.println("修狗的名字:"+dog1.name+" 修狗的年龄:"+dog1.age);//修狗的名字:萨摩耶 修狗的年龄:2}
}

四、Lambda表达式需要注意的问题

这⾥类似于局部内部类、匿名内部类,依然存在闭包的问题。

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


总结

以上就是Lambda表达式相关内容,本文仅简单介绍了Lambda表达式的使用,祝各位小伙伴们学习愉快,欢迎交流!

Java中Lambda表达式使用及详解相关推荐

  1. el表达式ne什么意思_JSP中EL表达式的用法详解(必看篇)

    EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...

  2. Java中的异常和处理详解

    Java中的异常和处理详解 参考文章: (1)Java中的异常和处理详解 (2)https://www.cnblogs.com/lulipro/p/7504267.html 备忘一下.

  3. Java中Lambda表达式和stream的使用

    Java中Lambda表达式和stream的使用 转自 [*https://www.cnblogs.com/franson-2016/p/5593080.html*] 简介 (译者注:虽然看着很先进, ...

  4. Java中Lambda表达式的使用

    目录 1 简介 2  Lambda表达式的组成 2.1  Lambda表达式的函数式接口 2.2 对接口的要求 3 Lambda使用 3.1 基本使用 3.2 使用Lambdas和Streams 4 ...

  5. Java中Unsafe类的原理详解与使用案例

    点击关注公众号,利用碎片时间学习 1 概述 本文基于JDK1.8. Unsafe类位于rt.jar包,Unsafe类提供了硬件级别的原子操作,类中的方法都是native方法,它们使用JNI的方式访问本 ...

  6. Java中lambda表达式去重_JAVA8中Lambda和Stream

    Java8于2014年3月份发布,其主要更新的特性有:函数式接口.Lambda 表达式.集合的流式操作.注解的更新.安全性的增强.IO\NIO 的改进.完善的全球化功能等,本文将介绍Lambda表达式 ...

  7. Java中Lambda表达式的使用(转)

    https://www.cnblogs.com/franson-2016/p/5593080.html 简介 (译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖" ...

  8. java中static修饰函数_详解java中static关键词的作用

    在java中,static是一个修饰符,用于修饰类的成员方法.类的成员变量,另外可以编写static代码块来优化程序性能:被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载 ...

  9. java中的setattribute_JSP request.setAttribute()详解及实例

    javascript request.setAttribute()详解 request.setAttribute()怎么用的? JSP1代码 String [] test=new String[2]; ...

最新文章

  1. golang 函数定义
  2. 联想计算机农村,农村的联想
  3. python项目-推荐 10 个有趣的 Python 练手项目
  4. sql server 批量删除临时表
  5. JAVA第一次实验 ——实验楼
  6. 不同的PCB混装方式及加工工艺
  7. 轻量级定时任务框架:APScheduler
  8. SAP UI5 应用开发教程之七 - JSON 模型初探
  9. Link Cut Tree 学习笔记
  10. zabbix解决中文乱码
  11. Spring Boot加载指定属性文件
  12. 无锡东亭计算机培训班,锡山区东亭办公自动化培训、电脑培训班有哪些?
  13. 小程序如何添加外部字体库
  14. 基于SpringBoot在线电影订票系统
  15. 点击轮播图片,链接跳转错误
  16. android手势动画
  17. Kafka消费者消费方式
  18. QGIS二次开发:加载XYZ Tiles形式的瓦片地图
  19. 微信内置浏览器清理缓存方法
  20. jquery:选择器【基础选择器、层级选择器、属性选择器和方法操作、过滤选择器、筛选选择器和方法,可见性过滤选择器】

热门文章

  1. 诊断和响应故障_执行闪回和数据库时间点恢复(Flashback and Database Point-in-Time Recovery)
  2. vue+axios 实现Excel下载
  3. python 查找字符串
  4. 只知道LinkedIn的你,错过了多少机会!美帝十大求职网站收好
  5. 在 Metaverse 中拥抱零售业的未来:你需要知道的一切
  6. 数据结构中ElemType是什么意思
  7. 月薪8万!这尼姑,你当不?
  8. 【沃顿商学院学习笔记】公益创业——03确定市场细分Identify market segmentation
  9. 基于opencv+python的角度测量
  10. Lenovo ideapad 15isk y700 固态限速问题的解决办法