Java的Lambda表达式和函数接口

Java的Lambda表达式和函数接口

下面主要将四个方面,并会给出具体的例子

  1. 函数接口
  2. lambda表达式
  3. 使用Lambda表达式作为函数接口参数
  4. 使用方法引用或构造器作为函数接口参数

1.函数接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法的接口

函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

如定义了一个函数式接口如下:

@FunctionalInterface //该注解只是显示的标注了接口用是一个函数接口,并强制编译器进行更严格的检查,如果不是就会报错。但也如果保证该接口是一个函数式接口也也可以不加该注解。
interface GreetingService 
{
    void sayMessage(String message);
}

函数式接口可以对现有的函数友好地支持 lambda。

2.lambda表达式

Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。

lambda 表达式的语法格式如下:

(parameters) -> expression
或 
(parameters) ->{ statements; }

组成格式即:

  1. (数据类型 参数名,数据类型 参数名…):用来向表达式主体传递接口方法需要的参数。在编写Lambda表达式时**,可以省略参数的数据类型,后面的表达式主体会自动进行校对和匹配**。同时,如果只有参数,则可以省略括号()
  2. -> : 表示lambda表达式箭牌,用来指向参数数据指向,不能省略,且必须用英文符号。
  3. {表达式主体}:由单个表达式或语句块组成的主体,本质就是接口中抽象方法的具体实现如果表达式主体只有一条语句,那么可以省略包含主体的大括号。另外,在lambda表达式主体中允许有返回值,当只有一条return语句时,也可以省略return关键字

lambda表达式多用于实现函数接口作为方法参数。

3.使用Lambda表达式实现函数接口

举一个例子

package learn;
import java.util.*;
interface FucInterface {
	public void print(String s);
}

public class Learn {
	public static void main(String[] args) {
		String s="ZZZzzzzZZZZZzzzzzzZZZZZ";
		ceshi(s, _s-> System.out.println("Lambda s:"+_s)  );
	}
	static public void ceshi(String s,FucInterface fuc) {
		fuc.print(s);
	}
	//Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ
}

在这里首先定义了一个函数接口FucInterface,接下来又定义了一个函数ceshi,改函数接受一个String参数和一个实现FucInterface 接口的对象,最后调用对象的print方法。

我们可以在使用ceshi函数时 FucInterface 接口的对象用lambda表达式代替,因为 FucInterface 接口是一个函数接口,这样lambda表达式会自动替换该接口的函数,所以在调用该接口的函数时,就会相当于调用该lambda表达式。


4.方法引用和构造器来作为函数接口参数

引用传智播客出品的java基础入门

使用方法引用和构造器,这两种形式可以进一个简化Lambda表达式的书写,其本质都是对Lambda表达式的主体部分已存在的方法进行直接引用,主要区别就是对普通方法和构造器方法的引用而已。

上面的黑体字是核心,表示使用这两种方法,其根本还是会被转化为Lambda表达式函数体调用。

种类 Lambda表达式示例 对应的引用示例
类名引用普通方法 (x,y,…)-> 对象名x.类普通方法(y…) 类名::类普通方法名
类名引用静态方法 (x,y,…)-> 类名.类静态方法(x,y…) 类名::类静态方法名
对象名引用方法 (x,y,…)-> 对象名.(x,y…) 对象名::实例方法名
构造器引用 (x,y,…)-> new 类名(x,y,…) 类名::new

其中第1种不容易理解,不过这里略过了O(∩_∩)O.

这里只阐述最常用的 类名引用静态方法,其他的不再描述

就以上面的例子为例,还可以这样写

package learn;
import java.util.*;
interface FucInterface {
	public void print(String s);
}
class Ces{
	static void output(String _s) {
		System.out.println("s:"+_s);
	}
}
public class Learn {
	public static void main(String[] args) {
		String s="ZZZzzzzZZZZZzzzzzzZZZZZ";
		ceshi(s, _s-> System.out.println("Lambda s:"+_s)  );
		System.out.println("============================");
		ceshi(s,_s->Ces.output(_s) );
		System.out.println("============================");
		ceshi(s,Ces::output);
	}
	static public void ceshi(String s,FucInterface fuc) {
		fuc.print(s);
	}
	//Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ
}
/* 输出: Lambda s:ZZZzzzzZZZZZzzzzzzZZZZZ ============================ s:ZZZzzzzZZZZZzzzzzzZZZZZ ============================ s:ZZZzzzzZZZZZzzzzzzZZZZZ */

其中第二种调用的方式与第三种等效。

这个过程可以理解为直接将Ces类的output函数 替换成接口函数的那个函数了。

全部评论

相关推荐

数开小菜鸡:你是我今早见过的最美的牛客女孩......
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务