目录
一、Lambda表达式简介
函数式编程是种编程范式,它将计算机运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演 算的函数可以接受函数当作输入(参数)和输出(返回值)。和指令式编程相比,函数式编程强调函数的计算比指令的执行重 要。和过程化编程相比,函数式编程里,函数的计算可随时调用。
(1)示例
为了理解Lambda表达式的概念,下面先从一个示例开始。
假设有这样的一个需求:设计一个通用方法,能够实现两个数值的加法和减法运算。Java中方法不能 单独存在,必须定义在类或接口中,考虑是一个通用方法,可以设计一个数值计算接口,其中定义该 通用方法,代码如下:
//可计算接口
public interface Calculable {
// 计算两个int值
int calculateInt(int a, int b);
/**
* 通过操作符进行计算
* @param opr 操作符
* @return 实现 Calculable接口对象
*/
public static Calculable calculable(char opr){
Calculable result;
if (opr == '+'){
// 匿名内部类实现Calculable接口
result = new Calculable() {
// 实现加法运算
@Override
public int calculateInt(int a, int b) {
return a+b;
}
};
}else{
// 内部类实现Calculable接口
result = new Calculable() {
@Override
public int calculateInt(int a, int b) {
return a-b;
}
};
}
return result;
}
}
调用通用方法代码如下:
//测试代码
public class HelloWorld {
public static void main(String[] args) {
int n1 = 10;
int n2 = 5;
// 实现加法计算Calculable对象
Calculable c1 = Calculable.calculable('+');
// 实现减法计算Calculable对象
Calculable c2 = Calculable.calculable('-');
// 调用calculateInt方法进行计算
System.out.printf("%d + %d=%d \n",n1,n2, c1.calculateInt(n1,n2));
// 调用calculateInt方法进行计算
System.out.printf("%d - %d=%d \n",n1,n2,c2.calculateInt(n1,n2));
}
}
(2)Lambda表达式实现
通过匿名内部类实现通用方法calculate代码很臃肿,Java 8采用Lambda表达式可以替代匿名内
部类。修改之后的通用方法calculate代码如下:
//可计算接口
@FunctionalInterface
public interface Calculable {
// 计算两个int值
int calculateInt(int a, int b);
/**
* 通过操作符进行计算
* @param opr 操作符
* @return 实现 Calculable接口对象
*/
public static Calculable calculable(char opr){
Calculable result;
if (opr == '+'){
// Lambda表达式实现Calculable接口
result = (int a, int b) ->{
return a+b;
};
}else{
// Lambda表达式实现Calculable接口
result = (int a, int b) ->{
return a-b;
};
}
return result;
}
}
二、Lambda表达式简化形式
使用Lambda表达式是为了简化程序代码,Lambda表达式本身也提供了多种简化形式,这些简化形式虽然简化了代码,但客观上使得代码可读性变差。
(1)省略参数类型
//可计算接口
@FunctionalInterface
public interface Calculable {
// 计算两个int值
int calculateInt(int a, int b);
/**
* 通过操作符进行计算
* @param opr 操作符
* @return 实现 Calculable接口对象
*/
public static Calculable calculable(char opr){
Calculable result;
if (opr == '+'){
// Lambda表达式实现Calculable接口
result = ( a, b) ->{
return a+b;
};
}else{
// Lambda表达式实现Calculable接口
result = ( a, b) ->{
return a-b;
};
}
return result;
}
}
(2)省略参数小括号
Lambda表达式中参数只有一个时,可以省略参数小括号。
(3)省略return和大括号
如果Lambda表达式体中只有一条语句,那么可以省略return和大括号,代码如下:
public static Calculable calculate(int power) {
Calculable result;
if (power == 2) {
// Lambda表达式实现Calculable接口
result = (int a) -> { //标准形式
return a * a;
};
} else {
// Lambda表达式实现Calculable接口
result = a -> a * a * a; //省略形式 1
};
return result;
}
三、作为参数使用Lambda表达式
Lambda表达式一种常见的用途是作为参数传递给方法。这需要声明参数的类型声明为函数式接口类型。
代码如下:
public class HelloWorld1 {
public static void main(String[] args) {
int n1 = 10;
int n2 = 5;
// 打印计算结果加法计算结果
diaplay((a,b)->{
return a+b;
},n1,n2);
// 打印计算结果减法计算结果
diaplay((a,b)->a-b,n1,n2);
}
/**
* 打印计算结果 *
* @param calc Lambda表达式
* @param n1 操作数1
* @param n2 操作数2 */
public static void diaplay(Calculable calc,int n1,int n2){
System.out.println(calc.calculateInt(n1,n2));
}
}
参数calc类型是Calculable,这个参数即可以接收 实现Calculable接口的对象,也可以接收Lambda表达式,因为Calculable是函数式接口。
四、访问变量
Lambda表达式可以访问所在外层作用域内定义的变量,包括:成员变量和局部变量。
(1)访问成员变量
成员变量包括:实例成员变量和静态成员变量。在Lambda表达式中可以访问这些成员变量,此时的Lambda表达式与普通方法一样,可以读取成员变量,也可以修改成员变量。
public class LambdaDemo {
// 实例成员变量
private int value = 10;
// 静态成员变量
private static int staticValue = 5;
// 静态方法,进行加法运算
public static Calculable add() {
Calculable result = (int a, int b) -> {
// 访问静态成员变量,不能访问实例成员变量
staticValue++;
int c = a + b +staticValue;
return c;
};
return result;
}
// 实例方法,进行减法运算
public Calculable sub() {
Calculable result = (int a, int b) -> {
// 访问静态成员变量和实例成员变量
staticValue++;
this.value++;
int c = a - b - staticValue - this.value;
return c;
};
return result;
}
}
(2)捕获局部变量
对于成员变量的访问Lambda表达式与普通方法没有区别,但是对于访问外层局部变量时,会发生“捕 获变量”情况。Lambda表达式中捕获变量时,会将变量当成final的,在Lambda表达式中不能修改那些捕获的变量。 示例代码如下:
public class LambdaDemo {
// 实例成员变量
private int value = 10;
// 静态成员变量
private static int staticValue = 5;
// 静态方法,进行加法运算
public static Calculable add() {
//局部变量
int localValue = 20;
Calculable result = (int a, int b) -> {
int c = a + b +staticValue;
return c;
};
return result;
}
// 实例方法,进行减法运算
public Calculable sub() {
//final局部变量
final int localValue = 20;
Calculable result = (int a, int b) -> {
// 访问静态成员变量和实例成员变量
staticValue++;
this.value++;
int c = a - b - staticValue - this.value;
return c;
};
return result;
}
}
五、方法引用
Java 8之后增加了双冒号“::”运算符,该运算符用于“方法引用”,注意不是调用方法。“方法引用”虽然没有直接使用Lambda表达式,但也与Lambda表达式有关,与函数式接口有关。 方法引用分为:静态方法的方法引用和实例方法的方法引用。它们的语法形式如下:
类型名::静态方法 // 静态方法的方法引用
实例名::实例方法 // 实例方法的方法引用
被引用方法的参数列表和返回值类型,必须与函数式接口方法参数列表和方法返回值类型 一致。
代码如下:
public class LambdaDemo {
// 静态方法,进行加法运算
// 参数列表要与函数式接口方法calculateInt(int a, int b)兼容
public static int add(int a, int b){
return a + b;
}
// 实例方法,进行减法运算
// 参数列表要与函数式接口方法calculateInt(int a, int b)兼容
public int sub(int a, int b) {
return a - b;
}
}
LambdaDemo类中提供了一个静态方法add,一个实例方法sub。这两个方法必须与函数式接口方法参数 列表一致,方法返回值类型也要保持一致。
代码如下:
public class HelloWorld {
public static void main(String[] args) {
int n1 = 10;
int n2 = 5;
// 打印计算结果加法计算结果
display(LambdaDemo::add, n1, n2);
LambdaDemo d = new LambdaDemo();
// 打印计算结果减法计算结果
display(d::sub, n1, n2);
}
/**
* 打印计算结果
* @param calc Lambda表达式 * @param n1 操作数1
* @param n2 操作数2
*/
public static void display(Calculable calc, int n1, int n2) {
System.out.println(calc.calculateInt(n1, n2));
}
}
以上内容仅供参考学习,如有侵权请联系我删除!
如果这篇文章对您有帮助,左下角的大拇指就是对博主最大的鼓励。
您的鼓励就是博主最大的动力!