Java8-方法引用和构造器引用

1. 方法引用

若lambda体中的内容有方法已经实现了,我们可以使用‘方法引用’,
可以理解为方法引用是lambda表达式的另外一种表现形式。双冒号形式
主要有三种语法格式

使用要求(注意点):

  • Lambda体中调用方法的参数列表、返回值类型 ,必须要和接口实现方法的参数列表、返回值保持一致

1.1. 对象::实例方法名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.1. 对象::实例方法名
@Test
public void test1(){
Consumer<String> con = (x) -> System.out.println(x);
con.accept("hxh");//hxh

Consumer<String> con1 = System.out::println;
con1.accept("hxh");//hxh 结果一致
//Consumer<T> 接口中的方法为: void accept(T t);
// println()方法实现为: public void println(String x)
/**
* 此处可以使用方法引用是因为 引用的方法println()的参数列表和返回值的类型 void println(String x)
* 与 Consumer<String> 接口实现的方法中的 void accept(String t) 的参数列表和返回值的类型
*/
}

1.2. 类::静态方法名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void test2(){
Supplier<String> sup = () -> new Object().toString();
System.out.println(sup.get()); //java.lang.Object@7d6f77cc

Supplier<String> sup1 = new Object()::toString;
System.out.println(sup1.get()); // java.lang.Object@6f75e721

Supplier<Double> sup2 = () -> Math.random();
System.out.println(sup2.get()); // 0.3782071825902372

Supplier<Double> sup3 = Math::random;
System.out.println(sup3.get()); // 0.1516143754943341
}

1.3. 类::实例方法名

该类型使用条件:

  • 第一个参数是实例方法的调用者,第二个参数是实例方法的参数
1
2
3
4
5
6
7
8
9
10
//类::实例方法名
@Test
public void test3(){
//BiPredicate<T,U> 俩参数的断言型接口
BiPredicate<String,String> bp = (x,y) -> x.equals(y);
System.out.println(bp.test("hxh","hxh")); //true
//(x,y) 括号里俩参数 第一个参数是调用方法对象,第二个参数是方法参数
BiPredicate<String,String> bp1 = String::equals;
System.out.println(bp1.test("hxh", "aaj"));//false
}

2. 构造器引用

  • 构造器,创建对象,自动匹配类中对应的构造器(参数不定)
  • 需要调用的构造器的参数列表要和函数式接口中的抽象方法参数列表保持一致

语法: ClassName::new;

实体类 Stu

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class Stu {
private Integer id;
private String name;
private Integer age;
public Stu() {
}
public Stu(Integer id) {
this.id = id;
}
public Stu(Integer id, Integer age) {
this.id = id;
this.age = age;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}

测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Test
public void test4(){
//无参构造
Supplier<Stu> stuSupplier = ()-> new Stu();
System.out.println(stuSupplier.get());
//自动匹配类中和接口实现的抽象方法中参数列表一致的构造器(无参构造器)
Supplier<Stu> stuSupplier1 = Stu::new;
System.out.println(stuSupplier1.get());
//Stu{id=null, name='null', age=null}

//有一个参数的构造
Function<Integer,Stu> s1 = (x) -> new Stu(x);
System.out.println(s1.apply(1)); //Stu{id=1, name='null', age=null}
//自动匹配类中和接口实现的抽象方法中参数列表一致的构造器(单个Integer的构造器)
Function<Integer,Stu> s2 = Stu::new;
System.out.println(s2.apply(2)); //Stu{id=2, name='null', age=null}

//有两个参数的构造 BiFunction<T, U, R> R apply(T t, U u);
BiFunction<Integer,Integer,Stu> bf = (x,y) -> new Stu(x,y);
System.out.println(bf.apply(3,44)); //Stu{id=3, name='null', age=44}
//自动匹配类中和接口实现的抽象方法中参数列表一致的构造器(两个个Integer的构造器)
BiFunction<Integer,Integer,Stu> bf1 = Stu::new;
System.out.println(bf1.apply(4,55));//Stu{id=4, name='null', age=55}
}

3. 数组引用

语法: Type[]::new;

1
2
3
4
5
6
7
8
9
//数组引用  Type[]::new
@Test
public void test5(){
//创建指定长度的字符串数组
Function<Integer,String[]> f1 = (x) -> new String[x];
System.out.println(f1.apply(10).length); //10
Function<Integer,String[]> f2 = String[]::new;//数组引用 可以直接代替
System.out.println(f2.apply(20).length); //20
}