若 Lambda 体中的功能,已经有相应的方法提供了实现,可以在Lambda体中引用该方法。(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)。
下面以一个简单实例演示
由于Consumer函数式接口如下
@FunctionalInterface
public interface Consumer {
/*传入一个类型,返回void*/
void accept(T t);
}
我们要用该接口的Lambda表达式实现字符串的输出功能,如下:
@Test
public void test(){
Consumer consumer = (s) -> {
if (s != null) {
System.out.println(s);
}else{
System.out.println("s 为空");
}
};
consumer.accept("lzj");
System.out.println("------------");
consumer.accept(null);
}
}
运行测试方法,输出:
lzj
------------
s 为空
此时,如果Lambda体中的内容已经被其它方法实现了,此时不必在Lambda体中再实现一遍了,直接调用相应的方法即可。例如有一个Info类中的show方法实现了相同的功能:
public class Info {
/*传入一个类型,返回一个void*/
public void show(T s){
if (s != null) {
System.out.println(s);
}else{
System.out.println("s 为空");
}
}
}
此时在用Consumer的函数接口Lambda表达式时,可以用下面的形式,实现了相同的功能。
@Test
public void test2(){
Info info = new Info<>();
Consumer consumer = info::show;
consumer.accept("lzj");
System.out.println("-----------");
consumer.accept(null);
}
在上面的示例中,Consumer接口中的accept方法的参数和返回值要和Info中的show方法中的参数和返回值一致方可用上面的形式。
Lambda的方法引用形式有以下三种形式
1. 对象的引用 :: 实例方法名
2. 类名 :: 静态方法名
3. 类名 :: 实例方法名
一、对象的引用 :: 实例方法名
1、用Lambda表达式实现打印字符串
@Test
public void test1(){
Consumer consumer = (x) -> System.out.println(x);
consumer.accept("lzj");
}
2、用Lambda的方法引用方式实现字符串打印
@Test
public void test1(){
PrintStream ps = System.out;
/*Consumer接口中的accept方法的参数和返回值同println方法的参数和返回值相同*/
Consumer consumer1 = ps::println;
consumer1.accept("lzj");
}
两种方式运行结果相同,都输出:lzj
二、类名 :: 静态方法名
例如我们要用Comparator接口的compare方法实现比较两个整数值的大小
1、用Lambda表达式表示如下
@Test
public void test3(){
Comparator<Integer> comparator =
(x, y) -> {
Integer differ = x < y ? -1 : ((x == y) ? 0 : 1);
return differ;
};
Integer differ1 = comparator.compare(10, 5);
System.out.println("differ1 : " + differ1);
}
2、用Lambda的方法引用
由于Integer类中的compare静态方法已经实现了比较两个整数的大小,重要的是,Integer中的compare方法与Comparator接口中的compare方法的参数和返回值一致。
@Test
public void test3(){
Comparator<Integer> comparator2 = Integer::compare;
Integer differ2 = comparator2.compare(10, 5);
System.out.println("differ2 : " + differ2);
}
以上两种形式运行,输出结果相同:differ1 : 1
三、类名 :: 实例方法名
1、用Lambda表达式实现比较两个字符串的大小
@Test
public void test4(){
BiPredicate<String, String> bp =
(x, y) -> {
Boolean flag = x.equals(y);
return flag;
};
Boolean flag = bp.test("lzj", "lzj");
System.out.println("flag : " + flag);
}
2、用Lambda的方法引用
String 类中的equals方法已经实现了比较两个字符串大小,可以通过该方法实现Lambda的方法引用。前两种方式都是函数式接口的输入参数和实现Lambda体功能的方法的传入方法一致,如果不一致时,函数式接口中两个参数,其中一个通过方法调用另一参数时可以用下面形式
@Test
public void test4(){
BiPredicate<String, String> bp1 = String::equals;
Boolean flag1 = bp1.test("lzj", "lzj");
System.out.println("flag1 : " + flag1);
}
BiPredicate接口中传入两个参数“lzj”和“lzj”,一个参数通过方法调用另一个,"lzj".equals("lzj")
,在用Lambda的方法引用时可以写成 String::equals的形式。
public class User {
private String name;
private Integer age;
public User() {
super();
}
public User(String name) {
super();
this.name = name;
}
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + "]";
}
}
1、用Lambda表达式实现分别通过User的无参构造器和一个有参构造器获得User对象
@Test
public void test5(){
Supplier supplier =
() -> {return new User();}; //() -> new User();如果Lambda体中只有一条语句,可以省略return
User user1 = supplier.get();
System.out.println("user1 : " + user1);
System.out.println("-----------------------------------");
Function function =
(x) -> {
User user = new User(x);
return user;
};
User user = function.apply("lzj");
System.out.println("user : " + user);
}
2、Lambda的构造器引用分别实现通过User的无参构造器和一个有参构造器获得User对象
@Test
public void test6(){
Supplier supplier = User::new;
/*get方法无参,有返回值,所以调用的User的无参构造器,返回User对象*/
User user1 = supplier.get();
System.out.println("user1 : " + user1);
System.out.println("-----------------------------------");
Function function = User::new;
/*apply方法有一个参数,有返回值,所以调用User的一个参数的构造器,并返回User对象*/
User user = function.apply("lzj");
System.out.println("user : " + user);
}
两种方式输出结果相同:
user1 : User [name=null, age=null]
-----------------------------------
user : User [name=lzj, age=null]
@Test
public void test7(){
Function function =
(x) -> new String[x]; //省略retuen的写法
String[] ss = function.apply(5);
System.out.println("ss.length : " + ss.length);
Function function1 = String[]::new;
String[] sss = function1.apply(5);
System.out.println("sss.length : " + sss.length);
}