若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用” (可以理解为方法引用是Lambda表达式的另一种表现形式)
一、方法引用:
主要语法格式
- 对象::实例方法名
下面是Lambda表达式与方法引用的对比
@Test
public void Test1() {
//Lambda表达式
Consumer<String> consumer1 = x -> System.out.println(x);
consumer1.accept("abcd");
//方法引用
PrintStream printStream=System.out;
Consumer<String> consumer = printStream::println;
consumer.accept("fadfa");
}
注意:使用方法引用的前提是Lambda体中调用方法的参数列表和返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。具体什么意思,我们用图片对比一下就可以了解。
这是PrintStream类中的println方法
这是Consumer接口中的抽象方法accept
从这两张图片可以看出两个方法都是无返回值,并且由于泛型,两个方法的参数都是String,所以满足使用方法引用的条件。
接下来我们对第一种语法格式来进行测试。
Person.java文件
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
@Test
public void Test2(){
Person person = new Person("张三",18);
//Lambda表达式
Supplier<String> supplier1=()->person.getName();
System.out.println("Lambda表达式:"+supplier1.get());
//方法引用
Supplier<Integer> supplier= person::getAge;
System.out.println("方法引用:"+supplier.get());
}
输出结果:
Lambda表达式:张三
方法引用:18
- 类::静态方法名
@Test
public void Test3(){
//Lambda表达式
Comparator<Integer> comparator=(x,y)->Integer.compare(x,y);
//方法引用
Comparator<Integer> comparator1=Integer::compareTo;
}
- 类::实例方法名
这种语法格式的使用前提要在前两种使用条件的基础上在加一条:
若Lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用类名::方法名
@Test
public void Test4(){
//Lambda表达式
BiPredicate<String,String> biPredicate=(x,y)->x.equals(y);
System.out.println(biPredicate.test("A","b"));
//方法引用
BiPredicate<String,String> biPredicate1 = String::equals;
System.out.println(biPredicate1.test("Ni","Ni"));
}
从上述代码中,可以看出参数x调用了String的equals方法,而方法参数正是参数y,满足条件,可以是方法引用。
输出结果:
false
true
三、构造器引用
语法格式:
ClassName::new
构造器引用的用法与方法引用的用法类似,需要调用的构造器的参数列表的类型要与函数式接口中抽象方法的参数列表的类型保持一致。
@Test
public void Test5(){
//Lambda表达式
Supplier<Person> supplier=()->new Person();
System.out.println(supplier.get());
//方法引用 Supplier<Person> supplier1=Person::new;
System.out.println(supplier1.get());
}
因为Supplier接口的抽象方法没有参数,实体类Person具有无参构造方法,所以可以使用构造器引用
下面我们来测试具有多个参数列表的方法
BiFunction接口是四大核心函数式接口Function的扩展,它的抽象方法具有将接口的前两个泛型转换为最后一种泛型的作用。
我在Person类中增加了一个构造器,这样与BiFunction接口的抽象方法的参数类型保持一致了。
@Test
public void Test6() {
BiFunction<String, Integer, Person> biFunction = Person::new;
Person person = biFunction.apply("李四", 19);
System.out.println(person);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
输出结果:
Person{name=‘李四’, age=19}
三、数组引用
语法格式:
Type[]::new
数组引用实例
@Test
public void Test7() {
//Lambda
Function<Integer, String[]> function = (x) -> new String[x];
System.out.println("数组长度:"+function.apply(10).length);
//数组引用
Function<Integer, String[]> function1=String[]::new;
System.out.println("数组长度:"+function1.apply(25).length);
}
输出结果:
数组长度:10
数组长度:25