1.方法引用是什么
方法引用,本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。所以 方法引用,也是函数式接口的实例。
2.使用情境
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
简单来说 正好lambda要写的抽象体是其他方法的方法体
听起来很绕其实就是说你的lambda表达式()->{}。其中{}里面的东西,已经有现有的实现方法了。
3.使用格式
类(或对象) :: 方法名
具体分为如下的三种情况:
- 情况1 对象 :: 非静态方法
- 情况2 类 :: 静态方法
- 情况3 类 :: 非静态方法
4.使用要求
要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的
形参列表和返回值类型相同!(针对于情况1和情况2)
5.代码展示
5.1对象 :: 非静态方法
public class MethodRefTest {
@Test
public void test1(){
MethodRefTest m1 = new MethodRefTest();
//传统写法
Runnable run1 = new Runnable() {
@Override
public void run() {
m1.print();
}
};
//lambda写法
Runnable run2 = ()->m1.print();
//方法引用写法
/*
* 分析:抽象方法 void run() 无形参 无返回值
* 实现方法 void print() 无形参 无返回值
* 可以用方法引用
*/
Runnable run3 = m1::print;
Thread t1 = new Thread(run1);
Thread t2 = new Thread(run2);
Thread t3 = new Thread(run3);
t1.start();
t2.start();
t3.start();
}
public void print(){
System.out.println("新的线程启动了");
}
}
好吧,这个无参无返回值的看不出什么,再来一个
@Test
public void test2(){
//传统写法
Consumer<String> con1 = new Consumer<String>() {
@Override
public void accept(String o) {
System.out.println(o);
}
};
//lambda写法
Consumer<String> con2 = o->System.out.println(o);
//方法引用写法
/*
* 分析:抽象方法 void accept(String o) 有一个类型为String 的形参 无返回值
* 实现方法 System.out.print(o) 有一个类型为String 的形参 无返回值
* 可以用方法引用
*/
Consumer<String> con3 = System.out::println;
con1.accept("传统写法");
con2.accept("lambda写法");
con3.accept("方法引用写法");
}
再看一个有参数也有返回值的
public String sum(String str){
return str+"123";
}
@Test
public void test3(){
MethodRefTest m = new MethodRefTest();
//传统写法
Function<String,String> fun1 = new Function<String, String>() {
@Override
public String apply(String s) {
return sum(s);
}
};
//lambda写法
Function<String,String> fun2 = s->m.sum(s);
//方法引用写法
/*
* 分析:抽象方法 String apply(String s) 有一个类型为String 的形参 类型为String返回值
* 实现方法 String sum(String str) 有一个类型为String 的形参 类型为String返回值
* 可以用方法引用
*/
Function<String,String> fun3 = m::sum;
System.out.println(fun1.apply("传统写法"));
System.out.println(fun1.apply("lambda写法"));
System.out.println(fun1.apply("方法引用写法"));
}
5.2类 :: 静态方法
@Test
public void test4(){
//传统写法
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
//lambda写法
Comparator<Integer> com2 = (o1,o2)->Integer.compare(o1,o2);
//方法引用写法
/*
* 分析:抽象方法 int compare(Integer o1, Integer o2) 有两个类型为Integer的形参 类型为int的返回值
* 实现方法 Integer 的int compare(int x, int y) 有两个类型为Integer的形参 类型为int的返回值
* 可以用方法引用
*/
Comparator<Integer> com3 = Integer::compare;
System.out.println("传统写法"+com1.compare(1,2));
System.out.println("lambda写法"+com2.compare(5,2));
System.out.println("方法引用写法"+com3.compare(1,9));
}
5.3类 :: 实例方法
这种情况和情况1
对象 :: 非静态方法
情况2 类 :: 静态方法
有所不同,体现在参数上
@Test
public void test5(){
//传统写法
Comparator<String> com1 = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
//lambda写法
Comparator<String> com2 = (o1,o2)->o1.compareTo(o2);
//方法引用写法
/*
* 分析:抽象方法 int compare(String o1, String o2) 有两个类型为 String 的形参 类型为int的返回值
* 实现方法 String 的int compareTo(String anotherString) 有一个类型为String的形参 类型为int的返回值
* 不可以用方法引用??? 并不是
* 这里可以看到 compare 的实现里面 o1是compareTo的调用者 这种情况下,我们可以用 类 :: 实例方法的方式去调用
*/
Comparator<String> com3 = String::compareTo;
System.out.println("传统写法:"+com1.compare("123","456"));
System.out.println("lambda写法:"+com2.compare("ABC","abc"));
System.out.println("方法引用写法:"+com3.compare("123AA","456aa"));
}