之前说了,Lambda表达式就是函数式接口实例
方法引用其实就是Lambda表达式的另一个写法,所以方法引用也就是函数式接口实例
来看几个Lambda表达式和方法引用的例子
-
对象::实例方法
@Test public void test() { List<Integer> list = new ArrayList<>(); list.add(4); list.add(7); list.add(9); // Lambda表达式 list.forEach(a -> System.out.println(a)); System.out.println("********************"); // 方法引用 list.forEach(System.out::println); }
out是System中定义的一个静态常量PrintStream对象,println()方法是PrintStream类的一个实例方法
-
类::静态方法
@Test public void test2() { // Lambda表达式 Function<Double, Double> function = a -> Math.sqrt(a); System.out.println(function.apply(16.0)); System.out.println("********************"); // 方法引用 Function<Double, Double> function2 = Math::sqrt; System.out.println(function2.apply(25.0)); }
sqrt是Math类中的一个静态方法
上面两种情况的使用条件:
函数式接口的抽象方法的参数列表、返回值类型要和方法引用的参数列表、返回值类型一样
-
类::实例方法
@Test public void test3() { Student student = new Student("小明", 25); // Lambda表达式 String name = Optional.ofNullable(student).map(a -> a.getName()).orElse(null); System.out.println(name); System.out.println("********************"); // 方法引用 String name2 = Optional.ofNullable(student).map(Student::getName).orElse(null); System.out.println(name2); }
第三种,类::实例方法,并不满足前面说到的,抽象方法和方法引用的参数列表和返回值一致,这是一个特殊的情况(就像类可以直接调实例方法一样,有点反常)
条件:函数式接口的抽象方法的第一个参数是该类的类型,其他剩余参数跟方法引用的参数列表一致
注:
常用的map方法(Stream的map、Optional的map等),需要传入一个Function<T,R>
函数式接口
该接口的抽象方法是R apply(T t)
,传入一个参数,返回一个参数
如果要使用 “类::实例” 形式的方法引用的话,根据上面的条件,那只需要传入的参数是该类(或子类)类型、方法引用的方法没有其他参数、返回值类型一致即可 -
没有 实例::静态方法 这种方法引用
总结:
- 方法引用其实就是Lambda表达式的另一个写法,所以方法引用也就是函数式接口实例
- 写Lambda表达式的时候想一想是否可以改成方法引用
- map方法,
Function<T,R>
函数式接口,需要快速反应改写成方法引用形式