1.基本介绍
java 8中一个非常重要的新特性就是lambda表达式,它允许把函数当作参数来使用,是面向函数式编程的一种思想。Lambda 表达式是一种匿名函数(对 Java 而言这并不完全正确,但现在姑且这么认为),简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。
2.为什么java需要lambda
在函数式编程语言中,函数是一等公民,它们可以独立存在,你可以将其赋值给一个变量,或将他们当做参数传给其他函数。函数式语言提供了一种强大的功能——闭包,相比于传统的编程方法有很多优势,闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。Java 现在提供的最接近闭包的概念便是 Lambda 表达式,虽然闭包与 Lambda 表达式之间存在显著差别,但至少 Lambda 表达式是闭包很好的替代者。
Lambda 表达式为 Java 添加了缺失的函数式编程特点,使我们能将函数当做一等公民看待。但是,在 Java 中,Lambda 表达式是对象,他们必须依附于一类特别的对象类型——函数式接口(functional interface),这个将在下面介绍。
3.基本表达式
(args) -> expression;
(args) -> {
statment1;
....
return statment;
}
4.lambda表达式的重要特征
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
5.一个简单的例子
/**
* @author wangC
* @version 1.0
* @date 2020/10/24 17:46
*/
public class LambdaTest {
public static void main(String[] args){
//相当于是创建了一个 MathInterface 的实现对象
//lambda表达式对应的是MathInterface#evaluate的实现方法,使用add.evaluate 来进行调用
MathInterface add = (x,y) -> x+y;
MathInterface substract = (x,y) -> x-y;
MathInterface multiply = (x,y) -> x*y;
MathInterface divide = (x,y) -> x/y;
System.out.println(add.evaluate(1,2));
System.out.println(substract.evaluate(10,5));
System.out.println(multiply.evaluate(2,3));
System.out.println(divide.evaluate(9,3));
HumanInterface wangC = name -> System.out.println("hai "+ name);
wangC.sayHai("wangC");
}
}
/**
* 函数式接口:函数式接口是只包含一个方法的接口。
*/
/**
* 创建方法有返回值的函数式接口
*/
@FunctionalInterface
interface MathInterface{
int evaluate(int x,int y);
}
/**
* 创建方法无返回值的函数式接口
*/
@FunctionalInterface
interface HumanInterface{
void sayHai(String name);
}
结果
3
5
6
3
hai wangC
6.lambda与1.7写法的比较
public class CompareTest {
public static void main(String[] args){
//匿名内部类的替换
//原有的写法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("in inner class version.");
}
}).start();
//lambda 的写法
new Thread(() -> System.out.println("in lambda version.")).start();
//lambda 表达式只能引用标记了 final 的外层局部变量,
// 这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
final String msg = "lambda 表达式只能引用标记了 final 的外层局部变量";
PrintInterface print = () -> System.out.println(msg);
print.printSomething();
String msg2 = "使用 Java 8 全新的双冒号(::)操作符将一个常规方法转化为 Lambda 表达式";
PrintBInterface pringB = System.out::println;
pringB.printSomething(msg2);
}
}
@FunctionalInterface
interface PrintInterface{
void printSomething();
}
@FunctionalInterface
interface PrintBInterface{
void printSomething(String message);
}
结果:
in inner class version.
in lambda version.
lambda 表达式只能引用标记了 final 的外层局部变量
使用 Java 8 全新的双冒号(::)操作符将一个常规方法转化为 Lambda 表达式
7.lambda与匿名内部类的区别
a.使用匿名类与 Lambda 表达式的一大区别在于关键词的使用。对于匿名类,关键词 this 解读为匿名类,而对于 Lambda 表达式,关键词 this 解读为写就 Lambda 的外部类。
b.Lambda 表达式与匿名类的另一不同在于两者的编译方法。Java 编译器编译 Lambda 表达式并将他们转化为类里面的私有函数,它使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法。