JavaSE笔记——Lambda表达式

news2025/4/27 8:59:48

文章目录

  • 前言
  • 一、第一个Lambda表达式
  • 二、如何辨别Lambda表达式
  • 三、引用值,而不是变量
  • 四、函数接口
  • 五、类型推断
  • 总结


前言

Java 8 的最大变化是引入了 Lambda 表达式——一种紧凑的、传递行为的方式。


一、第一个Lambda表达式

Swing 是一个与平台无关的 Java 类库,用来编写图形用户界面(GUI)。该类库有一个常见用法:为了响应用户操作,需要注册一个事件监听器。用户一输入,监听器就会执行一些操作:

Button button = new Button();
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("button clicked");
    }
});

设计匿名内部类的目的,就是为了方便 Java 程序员将代码作为数据传递。不过,匿名内部类还是不够简便。为了调用一行重要的逻辑代码,不得不加上 4 行冗繁的样板代码。这些代码还相当难读,因为它没有清楚地表达程序员的意图。我们不想传入对象,只想传入行为。在 Java 8 中,上述代码可以写成一个
Lambda 表达式,如下所示。

Button button = new Button();
button.addActionListener(e -> System.out.println("button clicked"));

和传入一个实现某接口的对象不同,我们传入了一段代码块——一个没有名字的函数。event 是参数名,和上面匿名内部类示例中的是同一个参数。-> 将参数和 Lambda 表达式的主体分开,而主体是用户点击按钮时会运行的一些代码。

和使用匿名内部类的另一处不同在于声明 event 参数的方式。使用匿名内部类时需要显式地声明参数类型 ActionEvent event,而在 Lambda 表达式中无需指定类型,程序依然可以编译。这是因为 javac 根据程序的上下文(addActionListener 方法的签名)在后台推断出了参数 event 的类型。这意味着如果参数类型不言而明,则无需显式指定。

二、如何辨别Lambda表达式

Lambda 表达式除了基本的形式之外,还有几种变体,如下所示:

Runnable runnable = () -> System.out.println("hello world"); // 1
ActionListener actionListener = e -> System.out.println("button clicked");// 2
Runnable runnable1 = () ->{
    System.out.print("Hello");
    System.out.println(" World");
}; // 3
BinaryOperator<Long> add = (x, y) -> x + y; // 4
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y; // 5
  1. 中所示的 Lambda 表达式不包含参数,使用空括号 () 表示没有参数。该 Lambda 表达式实现了 Runnable 接口,该接口也只有一个 run 方法,没有参数,且返回类型为 void。
  2. 中所示的 Lambda 表达式包含且只包含一个参数,可省略参数的括号。
  3. Lambda 表达式的主体不仅可以是一个表达式,而且也可以是一段代码块,使用大括号({})将代码块括起来,该代码块和普通方法遵循的规则别无二致,可以用返回或抛出异常来退出。只有一行代码的 Lambda 表达式也可使用大括号,用以明确 Lambda表达式从何处开始、到哪里结束。
  4. Lambda 表达式也可以表示包含多个参数的方法,这行代码并不是将两个数字相加,而是创建了一个函数,用来计算两个数字相加的结果。变量 add 的类型是 BinaryOperator<Long>,它不是两个数字的和,而是将两个数字相加的那行代码。
  5. 到目前为止,所有 Lambda 表达式中的参数类型都是由编译器推断得出的。这当然不错,但有时最好也可以显式声明参数类型,此时就需要使用小括号将参数括起来,多个参数的情况也是如此。

三、引用值,而不是变量

如果你曾使用过匿名内部类,也许遇到过这样的情况:需要引用它所在方法里的变量。这时,需要将变量声明为 final。将变量声明为 final,意味着不能为其重复赋值。同时也意味着在使用 final 变量时,实际上是在使用赋给该变量的一个特定的值。

String name = "saa";
Button button = new Button();
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("button clicked");
        System.out.println(name);
    }
});

Java 8 虽然放松了这一限制,可以引用非 final 变量,但是该变量在既成事实上必须是final。虽然无需将变量声明为 final,但在 Lambda 表达式中,也无法用作非终态变量。既成事实上的 final 是指只能给该变量赋值一次。换句话说,Lambda 表达式引用的是值,而不是变量。如果你试图给该变量多次赋值,然后在 Lambda 表达式中引用它,编译器就会报错。
在这里插入图片描述
这种行为也解释了为什么 Lambda 表达式也被称为闭包。未赋值的变量与周边环境隔离起来,进而被绑定到一个特定的值。在众说纷纭的计算机编程语言圈子里,Java 是否拥有真正的闭包一直备受争议,因为在 Java 中只能引用既成事实上的 final 变量。名字虽异,功能相同。

四、函数接口

函数接口是只有一个抽象方法的接口,用作 Lambda 表达式的类型。

使用只有一个方法的接口来表示某特定方法并反复使用,是很早就有的习惯。,Lambda 表达式也使用同样的技巧,并将这种接口称为函数接口。如下展示了前面例子中所用的函数接口:

public interface ActionListener extends EventListener {
    public void actionPerformed(ActionEvent e);
}

ActionListener 只有一个抽象方法:actionPerformed,被用来表示行为:接受一个参数,返回空。记住,由于 actionPerformed 定义在一个接口里,因此 abstract 关键字不是必需的。该接口也继承自一个不具有任何方法的父接口:EventListener。

这就是函数接口,接口中单一方法的命名并不重要,只要方法签名和 Lambda 表达式的类型匹配即可。可在函数接口中为参数起一个有意义的名字,增加代码易读性,便于更透彻地理解参数的用途。

常用的函数式接口:
在这里插入图片描述
在这里插入图片描述

五、类型推断

某些情况下,用户需要手动指明类型,建议大家根据自己或项目组的习惯,采用让代码最便于阅读的方法。有时省略类型信息可以减少干扰,更易弄清状况;而有时却需要类型信息帮助理解代码。经验证发现,一开始类型信息是有用的,但随后可以只在真正需要时才加上类型信息。

Lambda 表达式中的类型推断,实际上是 Java 7 就引入的目标类型推断的扩展。我们已经知道 Java 7 中的菱形操作符,它可使 javac 推断出泛型参数的类型。

Map<String, Integer> oldWordCounts = new HashMap<String, Integer>(); // 1
Map<String, Integer> diamondWordCounts = new HashMap<>(); // 2

我们为变量 oldWordCounts 1明确指定了泛型的类型,而变量 diamondWordCounts 2则使用了菱形操作符。不用明确声明泛型类型,编译器就可以自己推断出来。

如果将构造函数直接传递给一个方法,也可根据方法签名来推断类型。在下面例子中,如果将构造函数直接传递给一个方法,也可根据方法签名来推断类型。

useHashmap(new HashMap<>());
private void useHashmap(Map<String, String> values);

Java 7 中程序员可省略构造函数的泛型类型,Java 8 更进一步,程序员可省略 Lambda 表达式中的所有参数类型。javac 根据 Lambda 表达式上下文信息就能推断出参数的正确类型。程序依然要经过类型检查来保证运行的安全性,但不用再显式声明类型罢了。这就是所谓的类型推断。


总结

Lambda 表达式是一个匿名方法,将行为像数据一样进行传递。Lambda 表达式的常见结构:BinaryOperator<Integer> add = (x, y) → x + y。函数接口指仅具有单个抽象方法的接口,用来表示 Lambda 表达式的类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124868.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redhat7.6+grid 11.2.0.4部署遇到各种问题

一、add cluster node时&#xff0c;卡住 两个节点时间不同步&#xff0c;设置时间同步即可 二、部署Redhat7.6oracle11g部署中的bug Oracle 11.2.0.4 部署rac过程中&#xff0c;需要运行root.sh脚本报错。提示&#xff1a; ohasd集群无法启动。该补丁修改ohasd无法启动的问题…

红外成像系统测试

通常人们把红外辐射称为红外光、红外线。实际上其波段是指其波长约在0.75μm到1000μm的电磁波。人们将其划分为近、中、远红外三部分。近红外指波长为0.75-3.0μm;中红外指波长为3.0-20μm;远红外则指波长为20-1000μm。由于大气对红外辐射的吸收,只留下三个重要的“窗口”…

一把巴枪,和被改变的菜鸟驿站站长们

成立9年的菜鸟物流一直在答题。如果说之前这张答卷更多的标签是面向物流前端的配送和分拣等&#xff0c;那么如今&#xff0c;它的更多答案已经不单纯是前端的流通和连接&#xff0c;更有最末端基于科技对人的温度和赋能。 作者|丰兰 出品|产业家 数字化&#xff0c;正在…

少儿Python每日一题(6):角谷猜想

原题解答 本次的题目如下所示&#xff08;原题出处&#xff1a;NOC&#xff09;&#xff1a; 角谷猜想&#xff1a;以一个正整数n为例&#xff0c;如果n为偶数&#xff0c;就将它变为n/2&#xff1b;如果除后变成奇数&#xff0c;则将它乘3加1&#xff08;即3n1&#xff09;。…

latex常用语法速查

本文针对overleaf在线使用latex的情况编写。 文章目录文档结构要点导入图片使用表格添加引用参考资料文档结构 文档类型设置 \documentclass[12pt,article]{book} % []中设置文档格式&#xff0c;文档字体大小默认为10pt&#xff0c;article指定文档用纸类型&#xff0c;其他…

【金猿人物展】龙盈智达首席数据科学家王彦博:量子科技为AI大数据创新发展注入新动能...

‍王彦博本文由龙盈智达首席数据科学家王彦博撰写并投递参与“数据猿年度金猿策划活动——2022大数据产业趋势人物榜单及奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业回顾2022年大数据行业发展&#xff0c;令人感触最深的是数字经济时代对“数据安全”和“数…

基于自主可控的新型基础测绘与实景三维中国建设

实景三维中国作为强赋能、稳基底、重应用的新型基础设施&#xff0c;是打造数字中国、数字经济、数字政府的核心资源&#xff0c;其关键技术的掌握已经成为撬动社会生产&#xff0c;促进行业良性内循环&#xff0c;引发国家数字资源合理分配的重中之重。 ▲实景三维工程技术研究…

小程序入门01

目录 1.什么是小程序 2.小程序可以干什么&#xff1f; 3.相关资料 4.入门 4.1 申请账号 4.2 安装第一个小程序 4.3 了解程序 1.什么是小程序 2017年度百度百科十大热词之一 微信小程序&#xff08;wei xin xiao cheng xu&#xff09;&#xff0c;简称小程序&#xff0c;英文…

FreeSWITCH在视频会议中的实践经验

点击上方“LiveVideoStack”关注我们▲扫描图中二维码或点击阅读原文▲了解音视频技术大会更多信息// 编者按&#xff1a;视频会议已成为日常办公不可或缺的一部分&#xff0c;为远程交流的人们提供了许多便利。本次RTSCon 2022会议&#xff0c;由RTS社区和LiveVideoStack音视…

Win10的两个实用技巧系列之设置鼠标指针、红警玩不了怎么办?

win10系统怎么设置鼠标指针在打字时隐藏? win10隐藏鼠标指针的方法 win10系统怎么设置鼠标指针在打字时隐藏&#xff1f;win10系统输入文字的时候&#xff0c;想要隐藏鼠标指针&#xff0c;该怎么操作呢&#xff1f;下面我们就来看看win10隐藏鼠标指针的方法 win10如何隐藏鼠…

Android中的属性动画

在属性动画出来之前&#xff0c;Android系统提供的动画只有帧动画和View动画。View动画大家可能知道&#xff0c;它提供了AlphaAnimation(透明度)&#xff0c;RotateAnimation(负责旋转)&#xff0c;TranslateAnimation(负责移动)&#xff0c;ScaleAnimation(负责缩放)这4种动画…

2022年广西建筑安全员考试真题题库及答案

百分百题库提供建筑安全员考试试题、安全员证考试真题、安全员证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 100.《中华人民共和国建筑法》规定,建设单位申请领取施工许可证,应当具备下列条件有() A.已经办理该建筑工程用地批准手续…

手绘图说电子元器件-晶体管

晶体二极管与单结晶体管 晶体二极管是电子电路中最重要的半导体器件,包括一般二极管和特殊二极管两大类。 晶体二极管 晶体二极管简称二极管,是一种常用的具有一个PN结的半导体器件。 晶体二极管的极性 晶体二极管两引脚有正、负极之分 晶体二极管的参数 晶体二极管的…

HOW POWERFUL ARE GRAPH NEURAL NETWORKS? 论文/GIN学习笔记

对GNN的评估 GNN 通用表达式 聚合&#xff1a; av(k)AGGREAGTE(k)({hu(k−1):u∈N(v)})a_v^{(k)}AGGREAGTE^{(k)}(\{ h_u^{(k-1)} : u \in \mathcal{N}(v) \}) av(k)​AGGREAGTE(k)({hu(k−1)​:u∈N(v)}) 更新&#xff1a; hv(k)COMBINE(k)(hv(k−1),av(k))h_v^{(k)} COMB…

【JavaSE成神之路】流程控制语句

哈喽&#xff0c;我是兔哥呀&#xff0c;今天就让我们继续这个JavaSE成神之路&#xff01; 这一节啊&#xff0c;咱们要学习的内容是流程控制语句。 先来看概念 Java的流程控制语句是指用来控制程序执行流程的语句&#xff0c;它们可以改变程序的执行顺序&#xff0c;使程序更…

javaee之SpringMVC1

三层架构与MVC设计模式介绍 一张图介绍 之前在写软件设计的三层架构的时候&#xff0c;有一张图直接拿过来 springMVC的一些简单介绍 入门案例 一、入门案例之需求分析 二、搭建开发环境 1.利用骨架创建一个maven项目 因为这个项目要部署到服务器&#xff0c;所以采用如下骨…

代码质量与安全 | 如何将清洁代码标准扩展到整个企业,促进业务上的成功?

清洁代码能够让软件开发工作变得更简单、更有趣。因为如果代码不够清洁&#xff0c;开发人员将花费很多时间在解决编码问题上&#xff0c;使他们无法将精力投入开发新代码、解决其他更有趣的问题上。 那么&#xff0c;该如何将清洁代码标准扩展到整个企业呢&#xff1f;阅读本…

操作系统:进程与线程之间的区别及联系

一、定义 1、进程&#xff1a;进程是一个具有独立功能的程序关于某个数据集合的以此运行活动。 是系统进行资源分配和调度的独立单位&#xff0c;也是基本的执行单元。是一个动态的概念&#xff0c;是一个活动的实体。它不只是程序的代码&#xff0c;还包括当前的活动。 进程…

学习UI设计都可以学习哪些软件?

学UI设计要学习哪些工具软件&#xff1f;今天来做个大盘点 ​Photoshop(简称PS) 不懂设计的人也听说过PS著名大名。确切地说&#xff0c;确切地说&#xff0c;PS它是一款强大的综合性软件&#xff0c;主要用于位图处理&#xff0c;可以做图片处理&#xff0c;也可以做UI设计、平…

【财务】FMS财务管理系统---日常数据核对与处理

开发FMS财务管理系统&#xff0c;每天都会与数据打交道&#xff0c;数据的核对与处理是日常工作的一部分&#xff0c;相信接触过财务系统的同学都深有感触&#xff0c;为了一个差异查来查去&#xff0c;最终发现是前端业务系统的问题&#xff0c;白忙一场&#xff0c;本篇就说一…