Lambda表达式


1. 前言

结合官方文档,我们来研究一下Lambda表达式到底是什么?

2. Lambda是什么??

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。 — 菜鸟教程

看起来Lambda就是将函数作为参数传递进方法的表达式…那么这样做的好处是什么呢?

作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升 ,JDK 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。

看起来像是个语法糖,使用了它能够高效地编写代码,接下来看看语法吧~


3. Lambda的语法

看起来并不是非常的复杂:由一个括号()->{};组成,圆括号中放参数,方括号中是表达式具体内容。
(parameters) -> expression // 如果表达式只有一行,那么花括号可以省略…甚至一个参数的时候圆括号也可以省略 parameters -> expression

(parameters) ->{ statements; }

以下是lambda表达式的重要特征:

(1)可选类型声明 :不需要声明参数类型,编译器可以统一识别参数值。
(2)可选的参数圆括号 :一个参数无需定义圆括号,但多个参数需要定义圆括号。
(3)可选的大括号 :如果主体包含了一个语句,就不需要使用大括号。
(3)可选的返回关键字 :如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

看几个菜鸟教程给的例子

  1. 不需要参数,返回值为 5
() -> 5  
  1. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x  
  1. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y  
  1. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y  
  1. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)

4. 如何使用Lambda表达式?

使用 Lambda 表达式主要作用于函数式接口,传入的表达式则是对接口中唯一的方法的实现

(1) 什么是函数式接口?

一开始傻傻的以为,所谓“函数式接口”就是一个接口中只允许有一个方法。。其实是这样的:
函数式接口是除了Object提供的方法外,只包含一个抽象方法的接口。(当然JDK8允许的接口中的default以及static方法是可以有的…)

举个例子:下面这个就是一个函数式接口!

@FunctionalInterface
public interface LambdaTest {
    static void say(){
        System.out.println("这里是static方法");
    }
    void impl();
    default void hi(){
        System.out.println("这里是default方法");
    }
}

哦对了,关于**@FunctionalInterface注解**,我们可以在接口上面加上这个注解来检查该接口是否为函数式接口,如果不是,那么注解会爆红,编译不通过。(下面就是把除了Object方法外的唯一方法impl()删掉,则注解爆红)
在这里插入图片描述
我们可以测试一下其他情况:

(1)如果有两个自定义的方法?不是接口函数
在这里插入图片描述
(2)一个自定义方法加几个Object方法?是接口函数
在这里插入图片描述

@FunctionalInterface注解,非必须,可不加。。主要作用还是用来检验是否为函数式接口用的。

既然Lambda表达式的主体我们知道了是"函数是接口",并且我们也研究了什么是函数是借口,下一步我们来看看,lambda表达式具体如何作用于函数式接口


(2) lambda表达式具体如何作用于函数式接口?

如何作用于接口下面举个例子:

1.我们先创建一个函数式接口
在这里插入图片描述
2.在测试类中创建接口类的变量,并将接口中唯一抽象方法的具体实现利用Lambda表达式传入,使用变量调用这个传入了具体实现的唯一抽象方法。
在这里插入图片描述finally:于是该抽象方法便按照Lambda中传入的具体实现执行了
在这里插入图片描述
当然这只是Lambda作用于函数是接口最简单的使用方法(因为这个抽象方法返回值是void),我们也可以试试具有返回值的抽象方法,以及具有参数的抽象方法,Lambda该如何作用其方法上?
在这里插入图片描述

传入实现类的表达式以及返回值**(一行的时候可以直接写返回值不写return,如果有多行表达式,需花括号不能省略,return也需要写)**
在这里插入图片描述输出:
在这里插入图片描述

这样我们对Lambda表达式就基本掌握了
为了加深对Lambda表达式的印象,这里挑几段源码分析分析。


5. 源码中的Lambda是怎么用的?看几个例子加深理解!

在Spring框架中,AbstractBeanFactory类中

// Create bean instance.
if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		}
	});
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

可以看到这里getSingleton方法,第二个参数传递的是一个函数式接口的实现细节

我们将这个Lambda表达式剥离出来单独看看,他想要按照Bean的名字以及Bean的定义信息,创建一个Bean,如果失败则把它干掉。

() -> {
	try {
			return createBean(beanName, mbd, args);
		}catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	}

再来看看,这个Lambda表达式作用于什么函数式接口上?
因为这个Lambda表达式作为getSingleton的第二个参数传入,可以看到第二个参数是一个ObjectFactory

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {

进入这个ObjectFactory,其中有一个唯一的抽象方法getObject,就是传给他的!

@FunctionalInterface
public interface ObjectFactory<T> {
	/**
	 * Return an instance (possibly shared or independent)
	 * of the object managed by this factory.
	 * @return the resulting instance
	 * @throws BeansException in case of creation errors
	 */
	T getObject() throws BeansException;
}

那么这个T又是什么呢?参考我的另一篇文章: 添加链接描述


[暂时先记到这…有问题评论区探讨~peace!]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值