本文用使用大量内置函数式接口,可参考上篇文章:java8新特性之函数式接口使用
1.使用场景
当要传递给Lambda体的操作,已经存在实现的方法了,就可以使用方法引用。(抽象方法的参数列表 必须与方法引用方法的参数列表保持一致),可以理解为lambda的另一种表现形式。
2. 语法
使用操作符【::】将方法名和对象或类的名字分开。三种主要使用情况:
1)对象::实例方法名
注:消费型接口,参数类型为String,返回值为void,System.out.println(x)的参数类型也是String,返回值也是void,可以使用方法引用写法。
/**
* lambda 方法引用
* create by c-pown
*/
public class TestLambda {
public static void main(String[] args) {
//常规写法
Consumer<String> consumer = (x) -> System.out.println(x);
consumer.accept("张三");
//方法引用写法
Consumer<String> consum1 = System.out::println;
consum1.accept("李四");
}
}
张三
李四
2)类::静态方法名
注:消供给接口,参数类型为空,返回值为String,test1()的参数类型也是空,返回值也是String,可以使用方法引用写法。
public static void main(String[] args) {
//调用静态方法
//供给型接口,返回值为String
//类名::方法 返回值与Supplier接口返回值一致
Supplier<String> stringSupplier = TestLambda::test1;
String s = stringSupplier.get();
System.out.println(s);
}
public static String test1(){
System.out.println("王五");
return "王五";
}
3)类::实例方法名
这种写法有点特别,BiPredicate接口有两个,参数第一个参数必须是方法的调用者,第二个参数是方法的穿餐,才能够书写。否则会报错。
@Test
public void test2(){
//断言型几口子接口,传入两个参数,返回boolean
BiPredicate<String,String> stringSupplier1 = String::contains;
//类名::实例方法
//要注意:这种写法,第一个参数必须是方法的调用者,第二个参数是方法的参数,才能够书写
boolean test = stringSupplier1.test("abcde", "c");
System.out.println(test);
}
true
如果是普通方法,这种写法会报错。
二、构造器引用
语法:ClassName::new
@Test
public void test3(){
//原写法
Supplier<User> supplier = () -> new User();
User user = supplier.get();
System.out.println(user);
//引用写法
Supplier<User> supplier1 = User::new;
User user1 = supplier1.get();
System.out.println(user1);
}
User{age=0, name='null', job='null'}
User{age=0, name='null', job='null'}
我们发现这种写法,只能够获取一个无参的构造器。如何能够获取一个有参数的构造器呢?
package entity;
public class User {
private int age;
private String name;
private String job;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
//一个参构造方法
public User(int age) {
this.age = age;
}
//无参构造方法
public User() {
}
//有参构造方法
public User(int age, String name, String job) {
this.age = age;
this.name = name;
this.job = job;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
", job='" + job + '\'' +
'}';
}
}
//一个参构造方法
public User(int age) {
this.age = age;
}
我们在User类里面添加一个有一个参数的构造器。
Function<Integer,User> function = User::new;
User apply = function.apply(18);
System.out.println("一个参数构造器:"+apply);
User{age=0, name='null', job='null'}
User{age=0, name='null', job='null'}
一个参数构造器:User{age=18, name='null', job='null'}
使用Function函数传递一个Integer对象,发现调用的就是一个参数的构造器了。
参数的类型与个数,决定了调用的构造器是哪个。
如果对象没有当前类型构造器,使用构造器引用会报错。