Java方法引用可以视作是Lambda表达式更简洁的一种表达形式。准确来讲,当Lambda表达式的方法体满足特定条件的时候,就能将Lambda表达式替换为方法引用。这样的效果是使得代码更加简洁,可读性更强。
下面将按照顺序介绍方法引用,构造函数引用,数组引用,super引用。在这之前需要说明的是这些引用成立的首要前提是Lambda表达式的方法体有且仅有一行代码。
方法引用分为三种形式:
使用方法使用要求1.类 :: 静态方法1.函数式接口的方法的参数列表和类的静态方法的参数列表一一对应。2.函数式接口的方法返回类型和类的静态方法的返回类型一样。2.类 :: 实例方法1.实例方法的调用者的类型和函数式接口方法的第一个参数类型一致。2.函数式接口的方法的剩余参数列表和实例方法的参数列表一一对应。3.函数式接口的方法返回类型和实例方法的返回类型一样。3.对象 :: 实例方法1.函数式接口的方法的参数列表和实例方法的参数列表一一对应。2.函数式接口的方法返回类型和实例方法的返回类型一样。测试代码
package com.lordbao.test; import com.lordbao.entity.User; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; /** * @Author Lord_Bao * @Date 2020/10/3 19:10 * @Version 1.0 */ public class TestMethodReference { @Test public void testMethodReference(){ /** * 1. 方法引用 之 类 :: 静态方法 * 要求 : * 1).静态方法的参数列表和函数式接口对应的方法的参数列表相同 * 2).返回类型相同 * * 比如 Comparator<Integer> 的 Integer compare(Integer o1,Integer o2) * 和 Integer 的 静态方法 int compare(int o1,int o2) * 一一对应 */ List<Integer> list1 = Arrays.asList(1,9,3,2,6); list1.sort(Integer::compare); // list1.sort((x,y)->Integer.compare(x,y)); System.out.println(list1); /** * 2. 方法引用 之 类 :: 实例方法 * 要求 : * 1).实例方法的调用者和函数式接口的第一个参数类型相同 * 2).实例方法的参数列表和函数式接口方法的除了第一个参数以外的剩余参数类型一一对应 * 3).返回值类型相同 * * 比如 Comparator<Integer> 的 Integer compare(Integer o1,Integer o2) * 和 Integer 的 实例方法 int compareTo(int o) * 一一对应 */ List<Integer> list2 = Arrays.asList(1,9,3,2,6); list2.sort(Integer::compareTo); // list2.sort((x,y)->x.compareTo(y)); System.out.println(list2); /** * 3. 方法引用 之 类实例变量 :: 实例方法 * 要求 : * 1).实例方法的参数列表和函数式接口对应的方法的参数列表相同 * 2).返回类型相同 * * 比如 Consumer<Integer> : void consume(Integer t) * 和 PrintStream : void println(int x) * 一一对应 */ List<Integer> list3 = Arrays.asList(1,9,3,2,6); list3.forEach(System.out::println); } }构造函数引用的要求如下:
构造函数所在类的类型与函数式接口方法的返回类型相同。构造函数的参数列表与函数式接口的参数列表相同User
package com.lordbao.entity; /** * @Author Lord_Bao * @Date 2020/10/3 19:17 * @Version 1.0 */ public class User { private long id; private String username; public User() { } public User(long id) { this.id = id; } public User(long id, String username) { this.id = id; this.username = username; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + '}'; } }测试代码
@Test public void testConstructorReference(){ /** * 构造器引用 之 类::new * 要求 : * 1)、构造方法的参数列表和函数式接口对应的方法的参数列表相同 * 2)、类的类型 与 函数式接口的返回类型一致 */ Supplier<User> supplier = User::new; User user1 = supplier.get(); Function<Long, User> function = User::new; User user2= function.apply(1L); BiFunction<Long, String, User> biFunction = User::new; User user3 = biFunction.apply(2L, "jack"); }数组引用的要求如下:
函数式接口的方法参数只能有一个函数式接口的方法必须要有返回值因为(以String数组为例)
@Test public void testArrayReference(){ /** * 数组引用 * x->new String[x] 等价于 String[] :: new * 参数类型: Integer(表示数组长度) * 返回类型: String数组 */ Function<Integer,String[]> function1 = String[]::new; // Function<Integer,String[]> function1 = x->new String[x]; }super引用指的是在子类的方法里面可以引用父类的方法。具体的使用看代码。
package com.lordbao.test; import com.lordbao.entity.User; import org.junit.Test; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; /** * @Author Lord_Bao * @Date 2020/10/3 19:10 * @Version 1.0 */ public class TestMethodReference { @Test public void testSuperReference(){ new Son().say("??? 我怎么变成爸爸了"); } } class Father{ public void say(String words){ System.out.println("我是爸爸"); System.out.println(words); } } class Son extends Father{ @Override public void say(String words) { //在子类方法里面引用父类的方法 Consumer<String> consumer = super::say; consumer.accept(words); } }打印结果
我是爸爸 ??? 我怎么变成爸爸了
关于方法引用这一块,需要熟悉Lambda表达式和4个常见的函数式接口,开始觉得有点别扭,后来经常练习就会好得多。