欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java8新特性之方法引用与构造器引用

程序员文章站 2022-03-10 16:19:31
...

方法引用

若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”,可以理解为方法引用是Lambda表达式的另外一种表现形式;其主要有三种语法格式:

  1. 对象::实例方法名
  2. 类::静态方法名
  3. 类::实例方法名

对象::实例方法名

我们上一篇写到Java8内置的几个接口,我们用到其中的一个消费型接口做一个例子:

 @Test
    public void test1() {
        
        Consumer<String> con = x -> System.out.println(x);
        
    }

其中我们最最常用的输出,println()方法其实也是一个实例方法:
Java8新特性之方法引用与构造器引用
那么我们可以套上我们前面说到的 对象::方法名 这样的格式:

PrintStream ps = System.out;
Consumer<String> con1= ps::println;

Java8新特性之方法引用与构造器引用
但是这样用法有一个限制:Lambda体中被调用的方法的参数列表与返回值类型必须要与这个接口中被实现的抽象方法的参数列表与返回时一致;这么看着有点绕,我们来看一下,我们Consumer< T>消费型接口的抽象方法是:
Java8新特性之方法引用与构造器引用
再看看我们被调用的实例方法:
Java8新特性之方法引用与构造器引用
这时候我们就可以用对象::实例方法名的方式调用;看一个反例吧,先来用上我们上一篇文章用到的Employee员工类:

package Lambda;

public class Employee {

    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public void setName(String name) {
        this.name = name;
    }
    //测试用static方法
    public static void get(String s){
        System.out.println("haha");
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }


}

然后我们来测试:
Java8新特性之方法引用与构造器引用
最后我们使用一下吧:
Java8新特性之方法引用与构造器引用

类::静态方法名

这种情况没什么特别,直接上代码

 @Test
    public void test3() {

        Comparator<Integer> comparable = (x, y) -> Integer.compare(x,y);
        
        Comparator<Integer> comparable1 = Integer::compareTo;

    }

类::实例方法名

首先我们找一个两个参数的函数式接口:
Java8新特性之方法引用与构造器引用
来看看例子:

@Test
    public void test4() {

        BiPredicate<String, String> bp = (x, y) -> x.equals(y);

        BiPredicate<String, String> bp1 = String::equals;

    }

诶很奇怪,equals方法明明是一个实例方法呀?
Java8新特性之方法引用与构造器引用
为什么能通过类名String直接调用呢?其实这是有一个规则的:
Lambda表达式中,如果第一个参数是这个实例方法的调用者,而第二个参数是这个实例方法的参数时,就能用ClassName::method这种方式;

构造器引用

格式:ClassName::new

先来看一个供给型接口的例子,看看普通Lambda表达式的调用:

   @Test
    public void test5() {
	
        Supplier<Employee> sup = () -> new Employee();
        Employee employee = sup.get();

    }

然后来进化一下,怎么用以上格式快捷引用构造器呢?

 @Test
    public void test5() {
        
        Supplier<Employee> sup1 = Employee::new;
        Employee employee = sup1.get();

    }

我们可以看到用了这种构造器引用方式之后会把参数列表省略了,那如果我们有多个不同参数列表的构造器,JVM怎么辨别出我们是想调用哪一个呢?这里也有一个重点:**所引用构造器的参数列表要跟函数式接口抽象方法中的参数列表一致。**那么以上get()方法就是调用了参数列表为空的构造器了,我们来验证一下:
Java8新特性之方法引用与构造器引用
我们试一下怎么调用不同参数列表的构造器,先来一个函数型接口,复习一下:Java8新特性之方法引用与构造器引用
我们先给它来一个,只有一个参数的构造器:
Java8新特性之方法引用与构造器引用
来看看怎么引用的:

 @Test
    public void test6() {
        Function<String, Employee> fun = (x) -> new Employee(x);
        Function<String, Employee> fun1 = Employee::new;

        Employee employee = fun1.apply("Kelvin");
        System.out.println(employee);
    }

测试结果:
Java8新特性之方法引用与构造器引用

相关标签: lambda java