所谓方法引用,就是将已有的方法,作为lambda表达式的函数体进行调用,并返回执行结果。方法引用是特定场景的lambda表达式的简化。
语法:
类名::方法名称
class Person { |
等价于:
Comparator<Person> byName = Comparator.comparing(Person::getName); |
可以说方法引用是lambda的一种语法糖,简化了lambda表达式;就是函数体为一个表达式的lambda表达式; 而且方法引用的语义也更加明确,指明了调用特定的方法。
参数传递:
因为函数式接口的方法参数对应于隐式方法调用时的参数,所以被引用方法签名可以通过放宽类型,装箱以及组织到参数数组中的方式对其参数进行操作,就像在调用实际方法一样:
Consumer<Integer> b1 = System::exit; // void exit(int status) Consumer<String[]> b2 = Arrays:sort; // void sort(Object[] a) Consumer<String> b3 = MyProgram::main; // void main(String... args) Runnable r = Myprogram::mapToInt // void main(String... args) |
方法引用的种类:
类方法引用:
主要是引用成员方法、静态方法:
ClassName::methodName
引用普通成员方法:
因为调用成员方法必须基于某个对象,对比到lambda,实际上就是 :
(ClassName obj, [参数列表] )->obj.methodName( [参数列表] )
所以要求目标函数必须的参数数目是引用函数参数数目加1,第一个参数是方法的调用者;从第二个开始的参数个数要和需要调用方法的入参个数一致即可;
为了增强函数式接口的通用性,通常将其设计成泛型类型,以便可以引用不同类型的成员函数;
public interface TestInterface2<T> { |
public class TestC { public String aa(String a){ public void bb(){ |
引用静态成员方法:
因为静态成员方法不需要实例对象就可以调用,所以就相当于lambda:
( [参数列表] )->ClassName.methodName( [参数列表] )
目标函数的参数与引用函数参数列表相同;
public interface TestInterface3<T> { |
public class TestD { public static void aa(String a){ public static void main(String[] args) { |
引用泛型方法:
如果要引用的方法是泛型方法:
(1)可以在符号 ::之后指定实际类型:
ClassName::<T>methodName
(2)也可以不显式指定泛型类型,编译器可以通过相关参数推导得到泛型类型,这样就和普通的方法引用风格一致了。
public class Person { int age; public Person(String name, int age) { public Person() { |
public interface MyFun<T> { int func(List<T> list, T r); |
public class ListOpt { public static <T> int queryByAge(List<T> ts, T r){ |
public class Demo { public static void main(String[] args) { |
实例方法引用:
引用对象的成员函数
instanceName::methodName
引用实例方法,如果方法修改了实例自身的状态,则通过函数式接口调用目标函数时,也会修改实例的状态,实际上就是在lambda中引用了外部变量:
public class TestBN { private int i = 10; public static void main(String[] args) { |
引用父类方法:
super::methodName
public Runnable superTS(){ |
构造函数引用:
引用某个类型的构造函数来创建对象:
ClassName::new
public class TestBN { public static void main(String[] args) { |
数组构造函数引用:
type[]::new
public interface ArrayInitFun<T> { |
public class Demo { public static void main(String[] args) { ArrayInitFun<int[]> aif = int[]::new; int[] i = aif.create(5); //等于 new int[10]; System.out.println(i); } } |