了解方法引用之前要对lamda表达式要有一些了解所以可以看一下:前面有一篇聊的式Lambda表达式以及函数式几口的 地址
方法引用,这个式java1.8之后多的一个新特性,其实1.8式java继1.5版本之后最大改动的一个版本。
而方法引用这个对于这个名字可能有些不太熟悉,但是一定看见过(System.out :: println ),对于其中的两个:会不会有些懵。
老规矩先上代码后解释。
public class test {
public static void main(String[] args) {
// 方法1: 调用一次用匿名内部类实现,也是之前最常用的
tes t= new tes() {
@Override
public void get(String a) {
System.out.println(a);
}
};
t.get("你大爷");
// 方法2: Lambda
tes t1=(a)->System.out.println(a);
t1.get("你二大爷");
//方法3: 方法引用
PrintStream ps=System.out;//这里为啥会拆开,因为经常System.out.println,而无视了System.out式一个对象,而println是一个方法.
tes t2=ps::println;
t2.get("你三大爷");
//方法4: 方法引用 可以简化为
tes t3=System.out::println;
t3.get("你四大爷");
}
}
// 创建一个函数式接口
interface tes{
void get(String a);
}
这样可以看出方法引用的一些特点,以及如何和lamda挂钩的.
现在看一下对方法引用的实现的条件
- 当要传递给Lambda体的操作,已经有了实现的方法了,就可以使用方法引用了.
- 方法引用可以看成式Lambda表达式深层次的表达,简单的说就是方法引用就是Lambda表达式(毕竟Lambda本身返回得到就是函数式接口的实例),所以通过方法的名字指向一个方法.
看理论实话实说我也懵逼,因为是炒别人的.为什么抄,不抄的话感觉缺乏点牛逼的理论做支持.
现在用的我大白话说一遍:
方法引用,说白一个函数式接口,可以通过lambda表达式进行实现,同时其内部只有一行代码,这一行代码其调用了另一个类或者对象的方法,然后就可以有使用了方法引用的前提.
看上图就发现,如果有两行代码,你咋写?反正我没有找到如何写的方式,如果有知道的大佬可以告诉我一下.
格式
- 格式1:对象 :: 非静态方法
- 格式2: 类 :: 静态方法
- 格式3: 类 :: 非静态方法
有了前提那就需要有满足的条件了:
条件:
-
条件1 : 实现接口的方法返回值的类型,必须与方法引用的方法的返回值类型保持一致.
-
条件2: 参数列表两者也是两者一直必能用方法引用( 格式1,2 ).但是有些情况是例外,其调用的时候用其中一个参数调用方法用到了后面的参数(格式三).
(条件2的后半句有点绕,具体我们看代码)
代码演示 还是会普通方式以及lambda方式最后的方式调用,方便理解.
格式1:
public class test {
public void testprint(String b){
System.out.println(b);
}
public static void main(String[] args) {
tes t= new tes() {
@Override
public void get(String a) {
new test().testprint(a);
}
};
t.get("你大爷");
//lamda
tes t1=(a)->new test().testprint(a);
t1.get("你二大爷");
// 方法引用
tes t2 =new test()::testprint; //这个地方 方式发接口返回值void 参数都是一个而且都是String 类型
t2.get("你三大爷");
}
}
interface tes{
void get(String a);
}
格式2:
再次声明一下函数方法接口,不然使用Comparator这个函数接口的时候会发现其有很多方法在里面为什么还是函数式接口的疑问:
- 函数式接口只有一个抽象方法
- default方法某默认实现,不属于抽象方法
- 接口重写了Object的公共方法也不算入内
public class test {
public static void main(String[] args) {
// 普通方式
Comparator<Integer> C =new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return Integer.compare(o1, o1);
}
};
System.out.println(C.compare(2, 5));
// lambda
Comparator<Integer> C1= (Integer o1, Integer o2)-> {return Integer.compare(o1, o1);};
System.out.println(C1.compare(2, 5));
// 方法引用
Comparator<Integer> C2=Integer::compare; //这个返回值和参数列表也是都一样
System.out.println(C1.compare(2, 5));
}
}
格式3
public class sida {
public static void main(String[] args) {
// 普通方式
Comparator<Integer> C =new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o1.compareTo( o2);
}
};
System.out.println(C.compare(2, 5));
// lambda
Comparator<Integer> C1= (Integer o1, Integer o2)-> {return o1.compareTo( o2);};
System.out.println(C1.compare(2, 5));
// 方法引用
Comparator<Integer> C2=Integer::compareTo; //这个返回值一样,但是compareTo其参数不一样,用了第一个参数调用方法用第二个参数作为方法的参数
System.out.println(C1.compare(2, 5));
}
}
其实这个方法很多时候,可以用其实都主要式靠左侧,其中左侧就像是一个给java编译器一个招呼,这个对象是什么类型的.这一点多态的意思有点想,就是看左侧声明变量的类型,不然不可能实现lambda以及方法引用的.这个主要就是记住其规律,然后都用即可,没有什么编程逻辑在其中.