Lambda 表达式入门,看这篇就够了

简介:

01、初识 Lambda
Lambda 表达式描述了一个代码块(或者叫匿名方法),可以将其作为参数传递给构造方法或者普通方法以便后续执行。考虑下面这段代码:

() -> System.out.println("沉默王二")
来从左到右解释一下,() 为 Lambda 表达式的参数列表(本例中没有参数),-> 标识这串代码为 Lambda 表达式(也就是说,看到 -> 就知道这是 Lambda),System.out.println("沉默王二") 为要执行的代码,即将“沉默王二”打印到标准输出流。

有点 Java 基础的同学应该不会对 Runnable 接口感到陌生,这是多线程的一个基础接口,它的定义如下:

@FunctionalInterface
public interface Runnable
{
   public abstract void run();
}
Runnable 接口非常简单,仅有一个抽象方法 run();细心的同学会发现一个陌生的注解 @FunctionalInterface,这个注解是什么意思呢?

我看了它的源码,里面有这样一段注释:

Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

大致的意思就是说,通过 @FunctionalInterface 标记的接口可以通过 Lambda 表达式创建实例。具体怎么表现呢?

原来我们创建一个线程并启动它是这样的:

public class LamadaTest {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("沉默王二");
            }
        }).start();
    }
}
通过 Lambda 表达式呢?只需要下面这样:

public class LamadaTest {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("沉默王二")).start();
    }
}
是不是很妙!比起匿名内部类,Lambda 表达式不仅易于理解,更大大简化了必须编写的代码数量。

02、Lambda 语法
每个 Lambda 表达式都遵循以下法则:

( parameter-list ) -> { expression-or-statements }
() 中的 parameter-list 是以逗号分隔的参数。你可以指定参数的类型,也可以不指定(编译器会根据上下文进行推断)。Java 11 后,还可以使用 var 关键字作为参数类型,有点 JavaScript 的味道。

-> 相当于 Lambda 的标识符,就好像见到圣旨就见到了皇上。

{} 中的 expression-or-statements 为 Lambda 的主体,可以是一行语句,也可以多行。

可以通过 Lambda 表达式干很多事情,比如说

1)为变量赋值,示例如下:

Runnable r = () -> { System.out.println("沉默王二"); };
r.run();
2)作为 return 结果,示例如下:

static FileFilter getFilter(String ext)
{
    return (pathname) -> pathname.toString().endsWith(ext);
}
3)作为数组元素,示例如下:

final PathMatcher matchers[] =
{
        (path) -> path.toString().endsWith("txt"),
        (path) -> path.toString().endsWith("java")
};
4)作为普通方法或者构造方法的参数,示例如下:

new Thread(() -> System.out.println("沉默王二")).start();
需要注意 Lambda 表达式的作用域范围。

public static void main(String[] args) {

    int limit = 10;
    Runnable r = () -> {
        int limit = 5;
        for (int i = 0; i < limit; i++)
            System.out.println(i);
    };
}
上面这段代码在编译的时候会提示错误:变量 limit 已经定义过了。

和匿名内部类一样,不要在 Lambda 表达式主体内对方法内的局部变量进行修改,否则编译也不会通过:Lambda 表达式中使用的变量必须是 final 的。

03、Lambda 和 this 关键字
Lambda 表达式并不会引入新的作用域,这一点和匿名内部类是不同的。也就是说,Lambda 表达式主体内使用的 this 关键字和其所在的类实例相同。

来看下面这个示例。

public class LamadaTest {
    public static void main(String[] args) {
        new LamadaTest().work();
    }

    public void work() {
        System.out.printf("this = %s%n", this);

        Runnable r = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.printf("this = %s%n", this);
            }
        };
        new Thread(r).start();
        new Thread(() -> System.out.printf("this = %s%n", this)).start();
    }
}
Tips:%s 代表当前位置输出字符串,%n 代表换行符,也可以使用 n 代替,但 %n 是跨平台的。

work() 方法中的代码可以分为 3 个部分:

1)单独的 this 关键字

System.out.printf("this = %s%n", this);
其中 this 为 main() 方法中通过 new 关键字创建的 LamadaTest 对象——new LamadaTest()。

2)匿名内部类中的 this 关键字

Runnable r = new Runnable()
{
    @Override
    public void run()
    {
        System.out.printf("this = %s%n", this);
    }
};
其中 this 为 work() 方法中通过 new 关键字创建的 Runnable 对象——new Runnable(){...}。

3)Lambda 表达式中的 this 关键字

其中 this 关键字和 1)中的相同。

我们来看一下程序的输出结果:

this = com.cmower.java_demo.journal.LamadaTest@3feba861
this = com.cmower.java_demo.journal.LamadaTest$1@64f033cb
this = com.cmower.java_demo.journal.LamadaTest@3feba861
符合我们分析的预期。

04、最后
尽管 Lambda 表达式在简化 Java 编程方面做了很多令人惊讶的努力,但在某些情况下,不当的使用仍然会导致不必要的混乱,大家伙慎用。

好了,我亲爱的读者朋友们,以上就是本文的全部内容了。能在疫情期间坚持看技术文,二哥必须要伸出大拇指为你点个赞👍,疫情过后,我相信你的才华一定会展露无疑。

原创不易,如果觉得有点用的话,请不要吝啬你手中点赞的权力——因为这将是我写作的最强动力。

原文地址https://www.cnblogs.com/qing-gee/p/12286666.html

相关文章
|
4月前
|
Java
·Lambda的基本使用介绍
这篇文章详细介绍了Java中Lambda表达式的基本概念和使用方法,包括Lambda的基本语法、如何使用Lambda表达式实现接口方法、函数引用以及构造方法的引用,并通过实例代码展示了Lambda表达式的简洁性和实用性。
·Lambda的基本使用介绍
|
7月前
|
Java
Lambda 表达式复习
Lambda 表达式复习
36 1
Python知识点:lambda 表达式
lambda 表达可以被看做是一种匿名函数。它可以让你快速定义一个极度简单的单行函数。譬如这样一个实现三个数相加的函数:
|
SQL NoSQL Java
Java 进阶:使用 Lambda 表达式实现超强的排序功能
我们在系统开发过程中,对数据排序是很常见的场景。一般来说,我们可以采用两种方式: 借助存储系统(SQL、NoSQL、NewSQL 都支持)的排序功能,查询的结果即是排好序的结果 查询结果为无序数据,在内存中排序。
1427 0
Java 进阶:使用 Lambda 表达式实现超强的排序功能
|
并行计算 安全 Java
SpringCloudGateWay学习 之 从函数式编程到lambda
SpringCloudGateWay学习 之 从函数式编程到lambda
112 0
SpringCloudGateWay学习 之 从函数式编程到lambda
|
Java 编译器
Java 8 新特性:Lambda 表达式之方法引用(Lambda 表达式补充版)
Java 8 新特性:Lambda 表达式之方法引用(Lambda 表达式补充版)
232 0
Java 8 新特性:Lambda 表达式之方法引用(Lambda 表达式补充版)
|
编译器 C++
【c ++ primer 笔记】第4章 表达式
**运算对象转换** - `小整数类型(如bool、char、short等)通常会被提升成较大的整数类型,主要是 int 型` - 一般在进行二元运算符时,即使俩个数类型不一样,只要他们可以相互准换为同一个类型就可以。 - 运算符作用于类类型的运算对象时,用户可以自行定义其含义。这种做法称之为`重载运算符`
125 0
|
JavaScript 前端开发 Java
别翻了,Lambda 表达式入门,看这篇就够了(1)
别翻了,Lambda 表达式入门,看这篇就够了
161 0
别翻了,Lambda 表达式入门,看这篇就够了(1)
|
存储 自然语言处理 安全
Java 8 新特性:Lambda 表达式的作用域(Lambda 表达式补充版)
Java 8 新特性:Lambda 表达式的作用域(Lambda 表达式补充版)
672 0
|
Java 编译器
深入理解Java Lambda 表达式
Java 8 的 Lambda 表达式已经不再是“新特性”。 现在很多人工作中会使用 Lambda 表达式。 但是,你是否真正理解 Lambda 表达式的底层原理?
281 0
深入理解Java  Lambda 表达式