前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >面试官:说说Lambda表达式底层原理?

面试官:说说Lambda表达式底层原理?

作者头像
磊哥
发布于 2024-09-05 05:56:03
发布于 2024-09-05 05:56:03
19700
代码可运行
举报
文章被收录于专栏:王磊的博客王磊的博客
运行总次数:0
代码可运行

Lambda 表达式是 Java 8 引入的一种简洁的表示匿名方法的方式,使用它可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好。但 Lambda 表达式的底层是如何实现的呢?接下来我们一起来看。

1.未Lambda表达式

未使用 Lambda 表达式之前,我们创建一个线程,可以这样写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("t1");
    }
});
t1.start();

其中 Runnable 匿名内部类,查看 Runnable 源码,我们可以看到 Runnable 的实现如下:

1.1 什么是匿名内部类?

匿名内部类是在 Java 中定义的一个没有名称的内部类。它通常在一个类的成员位置或者方法体内直接定义,并且立即实例化。

匿名内部类的主要用途在于简化代码,避免为了实现一个简单的功能而定义一个完整的类。它特别适用于只需要一次使用的类,比如实现一个接口的单方法(即函数式接口)的场合。

PS:自从 Java 8 引入 Lambda 表达式后,很多原本使用匿名内部类的地方可以被更简洁的 Lambda 表达式替代。

上面代码中的 new Runnable 就是一个标准匿名内部类的使用。

1.2 什么是@FunctionalInterface?

@FunctionalInterface 是 Java 8 引入的一个注解,它用于标记一个接口为函数式接口

函数式接口是指只包含一个抽象方法的接口。这个注解虽然不是必需的,但它提供了一种明确的方式告诉编译器和开发者,这个接口是设计为函数式接口的。

@FunctionalInterface 注解的作用如下:

  1. 编译时检查:当一个接口被标记为 @FunctionalInterface 时,编译器会检查该接口是否只有一个抽象方法。如果不符合函数式接口的定义(即存在多个抽象方法),编译器会报错,提醒开发者修正。这为开发者提供了明确的编译时保障,确保所标记的接口确实符合函数式接口的要求。
  2. 代码明确性:即使不加 @FunctionalInterface 注解,只要接口符合函数式接口的定义,它仍然可以被视为函数式接口。但注解的存在增加了代码的明确性和可读性,使得其他开发者更容易理解该接口的设计意图。
  3. 支持 Lambda 表达式:函数式接口的主要目的是为了支持 Lambda 表达式。通过 Lambda 表达式,开发者可以以更简洁的方式实现函数式接口的抽象方法,从而减少模板代码,使代码更加简洁和易于理解。由于 Lambda 表达式本身不包含类型信息,Java 编译器需要一种机制来确定 Lambda 表达式对应的目标类型。函数式接口就扮演了这一角色——Lambda 表达式可以被赋值给任何兼容的函数式接口类型,编译器会依据接口的唯一抽象方法来推断 Lambda 表达式的参数类型和返回类型。

在 Java 标准库中,有许多使用 @FunctionalInterface 注解的接口,如 java.util.function 包下的 Function、Predicate、Consumer 等,这些接口都是函数式接口,广泛用于数据处理、过滤、转换等操作。此外,在 Spring Boot 框架中,也经常使用函数式接口来定义事件监听器、回调函数等。

2.使用Lambda表达式

未使用 Lambda 表达式之前,我们创建一个线程是这样写的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("t1");
    }
});
t1.start();

而用了 Lambda 表达式,我们可以这样写:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Thread t1 = new Thread(() -> { System.out.println("t1"); });
t1.start();

从上述代码可以看出,当我们使用 Lambda 表达式之后,代码就变得更简洁和优雅了。

3.Lambda详解

Lambda 表达式的语法形式如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(parameters) -> expression

或者是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(parameters) -> { statements; }

以上语法含义如下:

  1. 参数列表:在圆括号内的部分,用于定义传递给 Lambda 体的参数。参数列表可以为空,也可以包含多个参数,参数之间用逗号隔开。
  2. 箭头符号:是 Lambda 表达式的分隔符,将参数列表与表达式或语句块分隔开。
  3. Lambda 体:包含了具体的执行逻辑,可以是一个表达式或是一个由多个语句组成的代码块。

3.1 使用场景

Lambda 表达式主要用于执行函数式接口(Function Interface),即只有一个抽象方法的接口。常见的函数式接口包括 java.util.function 包下的 Predicate、Function、Consumer 等。

3.2 举个例子

假设我们有一个List,并且我们想要对这个列表进行过滤操作,只保留偶数元素。使用 Lambda 表达式可以非常方便地实现这一功能:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        // 使用 Lambda 表达式过滤出偶数
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());
        System.out.println(evenNumbers); // 输出 [2, 4, 6, 8]
    }
}

在这个例子中,n -> n % 2 == 0 是一个 Lambda 表达式,它接受一个整数 n 作为输入参数,并返回一个布尔值。这个 Lambda 表达式被用作 filter 方法的参数,该方法期望一个 Predicate 类型的函数式接口实例。

4.Lambda底层原理

Lambda 底层运行原理如下:

  1. 在程序运行时,会在类中生成一个匿名内部类,匿名内部类会实现接口,并重写接口中的抽象方法。
  2. 类中会生成一个静态方法,静态方法中的代码就是 Lambda 表达式中的代码。
  3. 匿名内部类重写的抽象方法,会调用上一步的静态方法,从而实现 Lambda 代码的执行。

所以,综合来说,Lambda 表达式其实是匿名内部类的语法糖,这个语法糖在程序执行时会进行兑现,也就是生成匿名内部类并进行任务执行。

课后思考

使用 javap 能否看出 Lambda 表达式的执行原理呢?说说具体的操作步骤。

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
面试官:说说Lambda表达式底层原理?
Lambda 表达式是 Java 8 引入的一种简洁的表示匿名方法的方式,使用它可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好。但 Lambda 表达式的底层是如何实现的呢?接下来我们一起来看。
磊哥
2024/09/04
2040
Java Lambda表达式:一旦学会就回不去了,谁用谁知道
自Java 8发布以来,许多样板代码都可以使用Lambda表达式替代。我真的想在Java中发表一篇关于 流 的文章,但是如果我们能将流与Lambda表达式结合起来,那么就肯定会带来真正的价值。因此,我就先写一下如何使用Lambda表达式。
烟雨平生
2023/03/07
4400
Java Lambda表达式:一旦学会就回不去了,谁用谁知道
java8 lambda 表达式详解
函数式接口是仅含一个抽象方法的接口,但可以指定 Object 定义的任何公有方法。
猿芯
2021/05/27
5440
java8 lambda 表达式详解
Java 学习笔记(11)——lambda 表达式
在写Java代码的时候,如果某个地方需要一个接口的实现类,一般的做法是新定义一个实现类,并重写接口中的方法,在需要使用的时候new一个实现类对象使用,为了一个简单的接口或者说为了一个回调函数就得额外编写一个新类,即使说使用匿名内部类来实现,这样似乎比较麻烦。C中的做法是直接传入一个函数指针,而Java中就需要上述麻烦的操作,能不能简单点呢?为此Java中引入了一个lambda表达式的功能。
Masimaro
2019/07/15
4170
深圳Java培训学习:Java8.0新特性之Lambda表达式
Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。本篇文章,主要给大家介绍的是lambda表达式。
深圳java培训技术
2019/10/28
5040
深圳Java培训学习:Java8.0新特性之Lambda表达式
《JAVA EE》内部类(下篇)&Lambda表达式的注意事项
定义在方法中(方法的形参或者实参),没有任何权限修饰符,甚至连类名称都没有的内部类称为匿名内部类。
VIBE
2022/12/02
3160
探索Lambda表达式:程序员视角下的数学之美与实战
Lambda表达式是Java 8 引入的一个重要特性,它允许将函数作为方法的参数传递,使得代码更加简洁和易读。Lambda表达式本质上是一个匿名函数,它可以代替传统的匿名内部类来实现函数式编程的思想。
不惑
2024/05/11
3800
探索Lambda表达式:程序员视角下的数学之美与实战
Java8之熟透Lambda表达式
​ Lambda 表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。
用户1195962
2019/09/29
5880
Java8之熟透Lambda表达式
java8系列01——函数式编程思想与Lambda表达式
java8引入了函数式编程,在工作中应用得特别广泛,如果不学习可能会看不懂公司中同事的代码。
半旧518
2022/10/26
3930
java8系列01——函数式编程思想与Lambda表达式
Java Review (十六、面向对象----Lambda 表达式)
当使用 Lambda 表达式代替匿名内部类创建对象时, Lambda 表达式的代码 块将会代替实现抽象方法的方法体, Lambda 表达式就相当一个匿名方法。
三分恶
2020/07/16
4960
Java8 Lambda表达式详解手册及实例「建议收藏」
先贩卖一下焦虑,Java8发于2014年3月18日,距离现在已经快6年了,如果你对Java8的新特性还没有应用,甚至还一无所知,那你真得关注公众号“程序新视界”,好好系列的学习一下Java8的新特性。Lambda表达式已经在新框架中普通使用了,如果你对Lambda还一无所知,真得认真学习一下本篇文章了。
全栈程序员站长
2022/09/08
1K0
(91) Lambda表达式 / 计算机程序的思维逻辑
在之前的章节中,我们的讨论基本都是基于Java 7的,从本节开始,我们探讨Java 8的一些特性,主要内容包括: 传递行为代码 - Lambda表达式 函数式数据处理 - 流 组合式异步编程 - CompletableFuture 新的日期和时间API 本节,我们先讨论Lambda表达式,它是什么?有什么用呢? Lambda表达式是Java 8新引入的一种语法,是一种紧凑的传递代码的方式,它的名字来源于学术界的λ演算,具体我们就不探讨了。 理解Lambda表达式,我们先回顾一下接口、匿名内部类和
swiftma
2018/01/31
6750
(91) Lambda表达式 / 计算机程序的思维逻辑
Java8 Lambda表达式与Stream API (一):Lambda表达式你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里
你要知道的Java8 匿名内部类、函数式接口、lambda表达式与Stream API都在这里 转载请注明出处 https://cloud.tencent.com/developer/user/1605429 本文主要讲解Java8 Stream API,但是要讲解这一部分需要匿名内部类、lambda表达式以及函数式接口的相关知识,本文将分为两篇文章来讲解上述内容,读者可以按需查阅。 Java 匿名内部类、lambda表达式与函数式接口 Java Stream API 本文是该系列博文的第一篇Java 匿名
WWWWDotPNG
2018/04/10
1.1K0
Lambda表达式
当需要启动一个线程去完成任务时,通常会通过 java.lang.Runnable 接口来定义任务内容,并使用java.lang.Thread 类来启动该线程。代码如下:
咕咕星
2020/08/19
5140
Lambda表达式
【Java】:lambda 表达式
🔥 Lambda 表达式 是JDK8新增的特性,Lambda 表达式 可以取代大部分匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以将函数作为一个方法的参数,也就是函数作为参数传递到方法中,极大地优化代码结构JDK也提供了大量的内置函数式接口供开发者使用,使得 Lambda 表达式 的运用更加方便、高效。
IsLand1314
2024/12/20
1280
【Java】:lambda 表达式
终于看懂别人的代码了!总结Java 8之Lambda表达式的写法套路
Thread里面需要传的是一个Runnable接口,为什么我们可以直接一个括号(),加上->,然后直接sout呢?
行百里er
2020/12/02
4530
终于看懂别人的代码了!总结Java 8之Lambda表达式的写法套路
Java 8 函数式接口、lambda表达式、方法以及构造器引用
我们知道,java是一门面向对象编程语言,java中一切都是面向对象的(除了原始数据类型)。在java中函数(方法)是类/对象的一部分,不能单独存在。而其他一些函数式编程语言如C++、Javascript等语言,可以编写单独的函数并可以直接调用它们。
青山师
2023/05/04
3740
Lambda表达式大揭秘:轻松玩转JDK 8的函数式魔法
Lambda表达式是Java 8中引入的一个核心特性,它提供了一种简洁、灵活的方式来表示一段可以传递的代码。Lambda表达式的本质是一个匿名函数,它允许我们将行为作为方法参数,或者将代码本身作为数据来处理。
王也518
2024/04/16
2330
9-Lambda表达式
Lambda表达式是JDK1.8开始之后的新技术,是一种代码的新语法,是一种特殊写法
Ywrby
2022/10/27
2230
【Java8新特性】Lambda表达式基础语法,都在这儿了!!
Lambda表达式在Java语言中引入了 “->” 操作符, “->” 操作符被称为Lambda表达式的操作符或者箭头操作符,它将Lambda表达式分为两部分:
冰河
2020/10/29
3730
【Java8新特性】Lambda表达式基础语法,都在这儿了!!
推荐阅读
相关推荐
面试官:说说Lambda表达式底层原理?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验