方法引用

方法引用(Method References)

  • 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

  • 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就 是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

  • 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致(参数个数不要求)!

  • 格式:使用操作符 “::” 将类(或对象) 与 方法名分隔开来。

如下三种主要使用情况:

  • 对象::实例方法名
  • 类::静态方法名
  • 类::实例方法名

image-20201221204840019

方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同!(针对于情况1和情况2)

对象::实例方法名

image-20201221205756019

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
//1.对象::实例方法
//Consumer中的void accept(T t)
//PrintStream中的void println(Object x)
@Test
public void test1() {

Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String str) {
System.out.println(str);
}
};
consumer.accept("世界");

//lambda简写
Consumer con1 = str -> System.out.println(str);
con1.accept("你好");

//方法引用使用PrintStream中的void println(T t)
PrintStream printStream = System.out;
Consumer tConsumer1 = printStream::println;
tConsumer1.accept("世界你好");

Consumer tConsumer = System.out::print;
tConsumer.accept("你好世界");
}

image-20201221205845296

image-20201221210058044

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2() {
Employee common = new Employee(10000, "common", 1, 0);
Supplier<String> s1 = new Supplier<String>() {
@Override
public String get() {
return common.getName();
}
};
System.out.println(s1.get());

//lambda表达式
Employee kylin = new Employee(10001, "kylin", 11, 1111);
Supplier<String> s2 = () -> kylin.getName();
System.out.println(s2.get());

//方法引用
Employee mr = new Employee(10001, "MethodRef", 7, 9999);
Supplier<String> s3 = mr::getName;
System.out.println(s3.get());
}

类::静态方法

image-20201223151226056

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//2.类::静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
//普通
Comparator<Integer> c1 = new Comparator<Integer>() {
@Override
public int compare(Integer t1, Integer t2) {

return Integer.compare(t1, t2);
}
};
System.out.println(c1.compare(12, 21));

//lambda
Comparator<Integer> c2 = (t1, t2) -> Integer.compare(t1, t2);
System.out.println(c2.compare(12, 21));


//方法引用,参数一样省略
Comparator<Integer> c3 = Integer::compare;
System.out.println(c3.compare(12, 21));
}

image-20201223151315803

image-20201223151553187

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4() {
//普通
Function<Double, Long> function1 = new Function<Double, Long>() {

@Override
public Long apply(Double d) {
return Math.round(d);
}
};
System.out.println(function1.apply(5.3));

//lambda
Function<Double, Long> function2 = (d) -> Math.round(d);
System.out.println(function2.apply(5.4));

//方法引用
Function<Double, Long> function3 = Math::round;
System.out.println(function3.apply(5.5));
}

image-20201223152157288

类::实例方法

image-20201223152128818

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//3.类::实例方法
//Comparator中的int compare(T t1,T t2)
//String中的int compareTo(String s)---->t1.compareTo(t2)
@Test
public void test5() {
//普通方法
Comparator<String> c1 = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
};

System.out.println(c1.compare("1", "4"));
//lambda
Comparator<String> c2 = (s1, s2) -> s1.compareTo(s2);
System.out.println(c2.compare("3", "7"));

//方法引用
Comparator<String> c3 = String::compareTo;
System.out.println(c3.compare("9", "1"));

}

image-20201223152224451

image-20201223152707844

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//BiPredicate中的boolean test(T t1,T t2);
//String中的boolean equals(O o)---->t1.equals(t2)
@Test
public void test6() {
//普通方法
BiPredicate<String, String> b1 = new BiPredicate<String, String>() {
@Override
public boolean test(String s1, String s2) {
return s1.equals(s2);
}
};
System.out.println(b1.test("a", "a"));

//lambda
BiPredicate<String, String> b2 = (s1, s2) -> s1.equals(s2);
System.out.println(b2.test("c", "a"));

//方法引用
BiPredicate<String, String> b3 = String::equals;
System.out.println(b3.test("e", "e"));
}

image-20201223152730198

结论

其中就是方法引用可以看做是Lambda表达式深层次的表达。使用方法引用必须保证该方法能和某一个对应的函数接口的方法返回值,参数类型保持一致。如果参数个数不一样例如

1
2
3
4
5
//Function中的R apply(T t)
//Employee中的String getName();--->t.getName();

//BiPredicate中的boolean test(T t1,T t2);
//String中的boolean equals(O o)---->t1.equals(t2)

如果想不到使用方法引用,则可以退而求其次使用lambda表达式,或者使用最普通的方式。这只是一种语法而已。只要求能看懂如果有相关源码中使用该语法能知晓真实意图做了啥即可。