jdk1.8新特性之lamada表达式
什么是lamada表达式
Lambda 表达式是一种匿名函数(对 Java 而言这并不完全正确,但现在姑且这么认为),简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。
它可以作为函数参数、函数返回值赋值给变量。
为什么用lamada表达式
在函数式编程语言中,函数是一等公民,它们可以独立存在,你可以将其赋值给一个变量,或将他们当做参数传给其他函数。JavaScript 是最典型的函数式编程语言。函数式语言提供了一种强大的功能——闭包,相比于传统的编程方法有很多优势,闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。Java 现在提供的最接近闭包的概念便是Lambda 表达式,虽然闭包与 Lambda 表达式之间存在显著差别,但至少 Lambda 表达式是闭包很好的替代者。
Lambda 表达式为 Java 添加了缺失的函数式编程特点,使我们能将函数当做一等公民看待。尽管不完全正确,我们很快就会见识到 Lambda 与闭包的不同之处,但是又无限地接近闭包。在支持一类函数的语言中,Lambda 表达式的类型将是函数。但是,在 Java 中,Lambda 表达式是对象,他们必须依附于一类特别的对象类型——函数式接口(functional interface)。我们会在后文详细介绍函数式接口。
lamada表达式结构
Java 中的 Lambda 表达式通常使用 (argument) -> {body}语法书写,例如:
(arg1, arg2...) -> { body }
(type1 arg1, type2 arg2...) -> { body }
(a) -> System.out.println(a);
a -> System.out.println(a);
a -> { System.out.println(a); };
(String a) -> { System.out.println(a); };
() -> System.out.println("Hello World");
(int a, int b) -> System.out.println(a + b);
- 一个 Lambda 表达式可以有零个或多个参数
- 参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)与(a)效果相同
- 所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
- 空圆括号代表参数集为空。例如:() -> 42
- 当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a
- Lambda 表达式的主体可包含零条或多条语句
- 如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返- 回类型与该主体表达式一致
- 如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空
函数式接口
lamada表达式是基于函数式接口上的基础上实现的。函数式接口是有且仅有一个抽象方法声明的接口。
这是两种new线程的方法,new Thread()需要的参数为Runnable接口实例对象。但是Runnable是一个接口,我们无法直接创建其对象,必须要先实现其抽象方法run()。jdk1.8之前我们的做法是匿名内部类或者新建Runnable的实现类。1.8引入了lamada表达式之后,我们对Runnable实现方法修改为下面代码中的方法。
// 非lamada表达式写法(匿名内部类)
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
// lamada表达式写法
new Thread(() -> System.out.println("hello world")).start();
但是,并不是所有的接口都是可以通过lamada表达式去进行实现的。其中的原因就是jdk1.8函数式接口加入。进入Runnable接口的源代码可以看到
@FunctionalInterface这个注解,通过这个注解可以声明Runnable接口是一个函数式接口。该注解声明后,才可以使用lamada表达式对原来的代码进行替换。
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
@FunctionalInterface注解必须声明在接口上,且接口有且仅有一个抽象方法,否则都后在编译阶段报错。通过@FunctionalInterface注解,我们可以定义一个函数式接口,使用lamada表达式对其方法进行实现。
如下代码,执行main方法会打印“haha”。
package io.yjff.lmada;
/**
* <函数式接口>
* @FunctionalInterface只能修饰有且仅有一个抽象方法的接口,否则都会编译报错
*
* @author 刘远杰
* @email 2634443725@qq.com
* @since 1.0 2020/5/15
*/
@FunctionalInterface
public interface TestClass1Interface {
void method1();
// void method2();
}
public static void main(String[] args) {
demo3();
}
public static void demo3() {
/**
* lamada表达式
*/
execute(() -> System.out.println("haha"));
}
public static void execute(TestClass1Interface worker) {
worker.method1();
}

本文深入探讨Java 8中引入的Lambda表达式,解释其概念、用途及结构,对比传统编程方式的优势,并详细说明如何在代码中应用,包括与函数式接口的结合使用。
2万+

被折叠的 条评论
为什么被折叠?



