在上一篇文章中曾经介绍到了java8中的Lambda表达式,这篇文章是基于Lambda表达式来叙述的。主要讲解方法引用。在此之前还希望你能够了解一下函数式接口的使用。

java8的一个新特性-Lambda表达式的详解(从0开始)

一、什么是方法引用

在Lambda表达式中,将其划分了几块。这一行就是lambda表达式。() -> System.out.println("使用Lambda表达式");下面我们对lambda的格式进行一个介绍:

(1)左边括号:lambda的形参列表,就好比是我们定义一个接口,里面有一个抽象方法,这个抽象方法的形参列表。

(2)箭头:lambda的操作符,所以你看见这个箭头心中知道这是一个lambda表达式就可以了。

(3)右边lambda体:就好比是我们实现了接口中的抽象方法。

在最后一块中,有时候,lambda体可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰。

所以我们来总结:方法引用是一个更加紧凑,易读的 Lambda 表达式,注意方法引用是一个 Lambda 表达式,其中方法引用的操作符是双冒号 "::"。

二、举例演示

1、我们首先定义一个User类

 1public class Person {
2    String name;
3    LocalDate birthday;
4    public Person(String name, LocalDate birthday) {
5        this.name = name;
6        this.birthday = birthday;
7    }
8    public LocalDate getBirthday() {
9        return birthday;
10    }
11    public static int compareByAge(Person a, Person b) {
12        return a.birthday.compareTo(b.birthday);
13    }
14    @Override
15    public String toString() {
16        return this.name;
17    }
18}

现在有一个功能,那就是需要按照年龄,对Person进行排序。

2、Lambda表达式写法

 1public class RefSort {
2    public static void main(String[] args) {
3        Person[] pArr = new Person[]{
4            new Person("1", LocalDate.of(2019121)),
5            new Person("2", LocalDate.of(2019122)),
6            new Person("3", LocalDate.of(2019123)),
7            new Person("4", LocalDate.of(2019124))};
8        Arrays.sort(pArr, (Person a, Person b) -> {
9            return a.getBirthday().compareTo(b.getBirthday());
10        });
11        System.out.println(Arrays.asList(pArr));
12    }
13}

我们使用lambda表达式可以直接进行比较。现在我们使用方法引用。

 1public class RefSort 
2    public static void main(String[] args) {
3        Person[] pArr = new Person[]{ 
4            new Person("1", LocalDate.of(2019121)),
5            new Person("2", LocalDate.of(2019122)),
6            new Person("3", LocalDate.of(2019123)),
7            new Person("4", LocalDate.of(2019124))};
8        Arrays.sort(pArr, Person::compareByAge);
9        System.out.println(Arrays.asList(pArr));
10    }
11}

这下子代码是不是更加的简洁了。我们相当于把lambda表达式进行了改变。下面我们就来好好地讲解一下方法引用是如何使用的。

三、方法引用分类

先来说一下方法引用使用到的操作符“::”,这个操作符把方法引用分成两边,左边是类名或者某个对象的引用,右边是方法名。引用方法有下面几种方式:

(1)对象引用::实例方法名

(2)类名::静态方法名

(3)类名::实例方法名

(4)类名::new

(5)类型[]::new

我们对这5种方式分别来叙述。

1、对象引用::实例方法名

 1public class PersonCompare {
2    public int compareByName(Person a, Person b) {
3        return a.getName().compareTo(b.getName());
4    }
5    public int compareByAge(Person a, Person b) {
6        return a.getBirthday().compareTo(b.getBirthday());
7    }
8    @Test
9    public void test(){
10        Person[] pArr = new Person[]{
11                new Person("1", LocalDate.of(2019121)),
12                new Person("2", LocalDate.of(2019122)),
13                new Person("3", LocalDate.of(2019123)),
14                new Person("4", LocalDate.of(2019124))};
15        PersonCompare personCompare = new PersonCompare();
16        Arrays.sort(pArr, personCompare::compareByName);
17    }
18}

我们创建了一个PersonCompare对象,调用了其内部的compareByName实例方法。

2、类名::静态方法名

举几个例子:

String::valueOf,等价于 Lambda:s -> String.valueOf(s)

Math::pow  等价于lambda表达式  (x, y) -> Math.pow(x, y);

Person::compareByAge 就是一个静态方法引用,也是前面我们举得例子。

1Function<Long, Long> f = Math::abs;
2Long result = f.apply(-3L);123

Math是一个类而abs为该类的静态方法。Function中的唯一抽象方法apply方法参数列表与abs方法的参数列表相同,都是接收一个Long类型参数。

3、类名::实例方法名

若Lambda表达式的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,就可以使用这种方法:

1BiPredicate<String, String> b = String::equals;
2b.test("abc""abcd");

String是一个类而equals为该类的定义的实例方法。BiPredicate中的唯一抽象方法test方法参数列表与equals方法的参数列表相同,都是接收两个String类型参数。

4、类名::new

在引用构造器的时候,构造器参数列表要与接口中抽象方法的参数列表一致。对应的 Lambda:() -> new String()。

 1class PersonFactory {
2    private Supplier<Person> supplier;
3    public PersonFactory(Supplier<Person> supplier) {
4        this.supplier = supplier;
5    }
6    public Person getPerson() {
7        return supplier.get();
8    }
9}
10PersonFactory factory = new PersonFactory(Person::new);
11Person p1 = factory.getPerson();

上面这段代码的功能就是使用PersonFactory工厂,然后使用Person::new创建一个Person实例。

5、类型[]::new

引用数组和引用构造器很像,格式为 类型[]::new,等价于 lambda 表达式 x -> new int[x]。其中类型可以为基本类型也可以是类。

1Function<Integer, int[]> fun = int[]::new;
2int[] arr = fun.apply(10);
3Function<Integer, Integer[]> fun2 = Integer[]::new;
4Integer[] arr2 = fun2.apply(10);

OK。方法引用就是这么简单。
这篇文章是我看着83版的聊斋完成的,里面故事情节的确吊打目前的流量明星,一句话点评,饱暖思淫欲呀。


更多相关文章

  1. java8的一个新特性-Lambda表达式的详解(从0开始)
  2. JS内存泄漏排查方法
  3. Java中的泛型方法
  4. 讲给前端的正则表达式(4):避免灾难性回溯[每日前端夜话0x105]
  5. 讲给前端的正则表达式(2):写出更优雅、更精确的正则表达式[每日前
  6. 讲给前端的正则表达式(1):基本概念
  7. 从模版方法模式到 SPI 演变 :好的思想通用而持久
  8. 讲给前端的正则表达式(3):使用 ES6 特性[每日前端夜话0x104]

随机推荐

  1. 包含文件include和require在php中的区别(
  2. PHP后端语言与前端JS语法的区别详解
  3. 使用PHPMailer在ThinkPHP5中发送电子邮件
  4. 构造函数在php中的使用方法(附示例)
  5. 使用 PHPStan 强化PHP代码质量
  6. php中函数参数传递的3种方式和区别(附详解
  7. php魔术方法简介
  8. PHP不适合高并发?
  9. 详解PHP中self关键字
  10. PHP去掉字符串中的“#”