概述
方法引用的本质是lambda表达式,使用场景为当要传递给lambda体的操作已经有实现的方法时,可以使用方法引用。
具体可以分为三种情况:
- 对象::非静态方法
- 类::静态方法
- 类::非静态方法
对象::非静态方法
以Consumer中的void accept(T t)
方法和PrintStream中的void println(T t)
方法为例,两者参数类型以及返回值类型均相同(这里没有返回值)。
测试方法如下:
//lambda
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("lambda");
System.out.println("---------------------");
//方法引用
//System.out返回的是一个PrintStream对象
Consumer<String> con2 = System.out::println;
con2.accept("methodRef");
结果如下:
lambda
---------------------
methodRef
类::静态方法
以Comparator中的int compare(T t1,T t2)
方法和Integer中的int compare(T t1,T t2)
静态方法为例,两者参数类型和返回值类型均相同
测试方法如下:
//lambda
Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(1, 2));
System.out.println("---------------------------");
//方法引用
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(1, 2));
结果如下:
-1
---------------------------
-1
类::非静态方法
此种情况和前两种参数列表和返回值类型都相同的情况不一样,个人觉得比较难以理解。
以Comparator中的int compare(T t1,T t2)方法和
String中的int t1.compareTo(t2)
方法为例,由于String中compareTo为非静态方法,只能由t1这个字符串对象调用。
测试方法如下:
//lambda
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("ab", "ac"));
System.out.println("--------------------------");
//方法引用
Comparator<String> com2 = String::compareTo;
System.out.println(com2.compare("ab", "ac"));
结果如下:
-1
--------------------------
-1
可以发现这里两个方法虽然参数列表不同,但是仍然可以引用,而且如果按照前两种情况理解,由类调用非静态方法也是不合法的,比较奇怪。个人理解为类::非静态方法,这种情况是将第一个参数作为调用非静态方法的对象,后面的参数则作为方法的参数列表。
总结
方法引用使用要求:
- 针对情况1和情况2,要求接口中的抽象方法的形参列表和返回值类型,与方法引用的方法的形参列表和返回值类型形同
- 对于情况3,方法引用的第一个参数是调用方法的对象,后续参数列表需要与方法的参数列表一致。当然返回值必须一致