Java语法中的方法引用::是个什么鬼?

目录

1.函数式接口

 2.Lambda表达式与"::"方法引用

 举例:

case1:

 case2:正式工作中用的比较多的stream流应用

case3:调用对象方法

case4:"::new"实例化对象

总结


 

1.函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法(通俗来说就是只有一个方法要去被实现,因此我们也能通过这个去动态推断参数类型),但是可以拥有多个非抽象方法的接口。函数式接口可以被隐式转换为lambda表达式。通常被用在Lambda表达式和方法引用上。

 2.Lambda表达式与"::"方法引用

方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文计算时,方法引用会创建函数式接口的一个实例

当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些。方法引用是一种更简洁易懂的Lambda表达式

 举例:

Person类结构

package com.yukuanyan.entity;

public class Person {
    private String name;

    private Integer age;

    public Person() {}

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public static int compare(Person a,Person b) {
        int r = a.getAge().compareTo(b.getAge());
        if (r != 0) {
            return r;
        } else {
            return a.getName().compareTo(b.getName());
        }
    }

    public static int compare(Person a,Person b,Person c) {
        return 0;
    }

    public Person concat(Person b) {
        this.setName(this.getName() + "," + b.getName());
        System.out.println(this);
        return this;
    }

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

    public void setName(String name) {
        this.name = name;
    }

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

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

case1:

package com.yukuanyan.cases;

import com.yukuanyan.entity.Person;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class case1 {

    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(new Person("zhangsan",33),new Person("lisi",22),new Person("wangwu",11));

        // 传统写法
        personList.sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });

        // Lambda 写法
        personList.sort((a,b) -> Person.compare(a,b));

        // 方法引用写法,调用static方法,参数类型动态推断
        personList.sort(Person::compare);

        System.out.println(personList);
    }
}

相信这里很多小伙伴会对方法引用写法有所疑问,明明Person类中有两个compare方法,java编译器是怎么直到应该使用哪个compare方法的呢?其实很简单。

我们点进去sort方法,sort方法需要传入一个函数式接口Comparator的实例 

我们点进Comparator这个接口

 

 可以看到抽象方法只有compare和equals,因为equals是继承自Object类,因此属于这个接口的抽象方法其实只有compare这一个接口,因此是符合函数式接口的定义的。

我们重点把目光放在compare接口的参数上,可以看到是

int compare(T o1, T o2);

 参数是两个,类型都是泛型。所以当我们引用Person类中的compare方法时,也会被java编译器推断出我们要使用的是两个参数的compare,而不是三个参数的compare

运行结果

 case2:正式工作中用的比较多的stream流应用

package com.yukuanyan.cases;

import com.yukuanyan.entity.Person;

import java.util.Arrays;
import java.util.List;

public class case2 {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(new Person("zhangsan",33),new Person("lisi",22),new Person("wangwu",11));

        personList.stream().sorted(Person::compare).forEach(System.out::println);
    }
}

case3:调用对象方法

package com.yukuanyan.cases;

import com.yukuanyan.entity.Person;

import java.util.Arrays;
import java.util.List;

public class case3 {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(new Person("zhangsan",33),new Person("lisi",22),new Person("wangwu",11));
        Person p = new Person("zhaoliu",44);
        personList.stream().sorted(Person::compare).forEach(p::concat);

    }
}

case4:"::new"实例化对象

package com.yukuanyan.cases;

import com.yukuanyan.entity.Person;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class case4 {
    public static void main(String[] args) {
        List<Person> personList = Arrays.asList(new Person("zhangsan",33),new Person("lisi",22),new Person("wangwu",11));
        Person p = new Person("zhaoliu",44);
        personList.stream().sorted(Person::compare).collect(Collectors.toCollection(ArrayList::new));

    }
}

总结

"::"俩冒号本质上就是方法引用,java编译器会根据需要的参数(Q:这里的参数格式来自于哪?A:来自于函数式接口中的抽象方法的参数列表)自动进行匹配。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值