Java8-Lambda:Lambda语法

本文深入探讨Java8中Lambda表达式的语法与应用,包括不同格式的Lambda表达式,如无参数无返回值、有一个参数无返回值以及有多个参数有返回值的表达式。同时,介绍了函数式接口的概念及其在Lambda表达式中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

又是热爱学习的一天!!!
在这里插入图片描述在这里插入图片描述

语法简介

Java8引入了一种新的操作符 “->”,该操作符叫做 箭头操作符 或者叫做 Lambda 操作符。箭头操作符将Lambda表达式分为了左右两部分

  • 左侧:Lambda 表达式的参数列表。
  • 右侧:Lambda 表达式所需执行的功能,也叫Lambda体。

上一篇 初识Lambda文章说道 ,Lambda表达式就是对接口的实现。以前是用匿名内部类去实现的接口,现在是用的Lambda表达式去实现的。

拿上篇文章的 StudentFilter 接口举例,接口中有个 filter 抽象方法。那么Lambda表达式的左侧就代表的 filter 方法的参数列表。Lambda表达式的右侧就是这个方法具体实现的功能

这里有一个疑问:Lambda 表达式自动的就找到了StudentFilter 接口中的 filter 抽象方法,如果这个接口中有多个抽象方法呢?该怎么办?
这里引出一个新概念:函数式接口

函数式接口

所谓函数式接口就是指接口中只有一个抽象方法的接口,我们称为函数式接口。
可以使用注解:@FunctionalInterface 来修饰
如果使用了该注解,那么就可以检测这个接口是不是函数式接口,不写也可以,但是得人工保证函数式接口的规范。而 Lambda 表达式就必须依赖一个函数式接口!

因为函数式接口的抽象方法可能是多种多样,比如无参数无返回值、无参数有返回值、有参数无返回值和有参数有返回值等多种情况,那么就有对应的几种略微不同的写法。

语法格式

语法格式一:无参数无返回值

我们在前面说到,Lambda表达式需要函数式接口的支持,那这里我们是不是需要新创建一个接口,并且增加一个无参数无返回值的抽象方法呢?
其实不用,这种抽象方法其实在Java中已经有一个了,比如:Runnable 接口就是一个函数式接口,接口中的 run 方法就是 无参数无返回值的。

 /**
 * 语法格式一:无参数无返回值
 *     () -> System.out.println("Hello Lambda")
 */
@Test
public void grammar_1(){
    // 原来匿名内部类的写法
    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello Inner class");
        }
    };
    r.run();

    System.out.println("************昏 哥 线*************");

    // 现在使用 Lambda 表达式的写法
    Runnable runnable = () -> System.out.println("Hello Lambda");
    runnable.run();
}

执行结果:

Hello Inner class
************昏 哥 线*************
Hello Lambda

这里需要提一点: 在 jdk 1.7及以前 如果一个局部类 引用了一个局部变量,那么这个变量 需要显示的声明成 final,在 1.8中就不用显示的去声明了,编译器默认给我们加上了,但是这个变量任然是 final 的,是不可以修改的,使用如下所示:

@Test
public void grammar_1(){
    int num = 25; // jdk 1.7及以前,需要显示的声明成 final
    // 原来匿名内部类的写法
    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello Inner class" + num);
        }
    };
    r.run();

    System.out.println("************昏 哥 线*************");

    // 现在使用 Lambda 表达式的写法
    Runnable runnable = () -> System.out.println("Hello Lambda" + num);
    runnable.run();
}

语法格式二:有一个参数 无返回值

有一个参数,无返回值的这个接口。 Java里面也有现成的,他就是:Consumer 接口,它里面的 accept 抽象方法就符合我们的要求:

/**
 * 语法格式二:有一个参数 无返回值
 *     (x) -> System.out.println(x)
 *
 * 注意:如果只有一个参数,那么 Lambda表达式左侧小括号可以省略不写,但是建议还是写上。
 */
@Test
public void grammar_2(){
    Consumer consumer = (x) -> System.out.println(x);
    consumer.accept("你好,Lambda");
}

语法格式三:有两个及以上参数 有返回值,并且 Lambda体中有多条语句

这种接口Java里面也有!它就是:Comparator 接口,它里面的 compare 方法就符合我们的要求:

/**
 * 语法格式三:有两个及以上参数 有返回值,并且 Lambda体中有多条语句,那么 Lambda 体需要使用大括号括起来。
 *
 * 注意:如果两个及以上参数 有返回值,但是 Lambda 体只有一条语句的话,那么 return 和 大括号可以省略不写。
 */
@Test
public void grammar_3(){
    Comparator<Integer> comparator = (x, y) -> {
        System.out.println("这是多条语句的 Lambda 体...");
        return Integer.compare(x, y);
    };

    int result = comparator.compare(100, 200);
    System.out.println("返回值为:"+result);

    System.out.println("************昏 哥 线*************");

    // 这是 Lambda 体只有一条语句的话,那么 return 和 大括号可以省略不写 的情况。
    Comparator<Integer> c = (x, y) -> Integer.compare(x, y);
    int result2 = c.compare(200, 500);
    System.out.println("返回值为:"+result2);
}

回头看几个 Lambda 语句,会发现 小括号里面的参数都是没有数据类型的,但是编译运行都没有问题,这就说明了,Lambda表达式的参数列表的数据类型可以省略不写,因为 JVM 编译器可以通过上下文推断出数据类型,这个过程就叫做 类型推断

番外

在上面说到函数式接口中只能有一个抽象方法,但是 Comparator 接口中除去 default 修饰的方法之外,还有两个,分别是:compare 和 equals。那么它为啥还是属于函数式接口呢?
原因就是 equals 它是 Object的方法,他已经有了默认实现,所以他不算是接口中的抽象方法

从 类的注释来看,可以总结出以下三点:

  1. 一个函数式接口有且只有一个抽象方法。
  2. 默认方法不是抽象方法,因为它们已经实现了。
  3. 重写了超类Object类中任意一个public方法的方法并不算接口中的抽象方法。

所以说 Comparator 接口还是只有 compare 这一个抽象方法,所以他符合函数式接口的标准

简单示例

需求:对指定数字进行运算

先创建一个函数式接口

@FunctionalInterface
public interface ICalculation<T> {
    int calc(T x, T y);
}

再写一个操作方法 operation,具体进行什么运算现在还不知道,我们对传入的参数 x 和参数 y 进行运算并返回结果。

public int operation(int x, int y, ICalculation<Integer> iCalculation){
	return iCalculation.calc(x, y);
}

调用 操作方法 operation,传入实参,使用 Lambda 表达式实现接口中的抽象方法进行运算。下面演示了乘法、加法和减法运算。

@Test
public void lambdaGrammar(){
    int operation = operation(10, 5, (x, y) -> x * y);
    System.out.println("乘法运算结果:"+operation);
    System.out.println("*******昏 哥 线************");

    System.out.println("加法运算结果:"+operation(10, 5, (x, y) -> x + y));
    System.out.println("*******昏 哥 线************");

    System.out.println("减法运算结果:"+operation(10, 5, (x, y) -> x - y));
}

运行结果:

乘法运算结果:50
*******昏 哥 线************
加法运算结果:15
*******昏 哥 线************
减法运算结果:5

总结
Lambda 表达式的语法其实比较简单,重点是分清它左右侧分别是什么内容,它的左侧就对应着函数式接口中抽象方法的参数列表,在它的左侧是可以不用写数据类型的,是因为有类型推断机制。如果非要写上数据类型,那就必须将所有参数都加上数据类型才可以。
它的右侧就是 Lambda 体,就是我们具体实现的内容,如果有多条语句需要使用大括号,只有一条语句可以省略大括号不写。
在这里插入图片描述


技 术 无 他, 唯 有 熟 尔。
知 其 然, 也 知 其 所 以 然。
踏 实 一 些, 不 要 着 急, 你 想 要 的 岁 月 都 会 给 你。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值