JAVA 8 方法引用 - Method References

什么是方法引用

  简单地说,就是一个Lambda表达式。在Java 8中,我们会使用Lambda表达式创建匿名方法,但是有时候,我们的Lambda表达式可能仅仅调用一个已存在的方法,而不做任何其它事,对于这种情况,通过一个方法名字来引用这个已存在的方法会更加清晰,Java 8的方法引用允许我们这样做。方法引用是一个更加紧凑,易读的Lambda表达式,注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。

方法引用例子

先看一个例子

首先定义一个Person类,如下:

package methodreferences;

import java.time.LocalDate;

public class Person
{

    public Person(String name, LocalDate birthday)
    {
        this.name = name;
        this.birthday = birthday;
    }

    String name;
    LocalDate birthday;

    public LocalDate getBirthday()
    {
        return birthday;
    }

    public static int compareByAge(Person a, Person b)
    {
        return a.birthday.compareTo(b.birthday);
    }

    @Override
    public String toString()
    {
        return this.name;
    }
}

假设我们有一个Person数组,并且想对它进行排序,这时候,我们可能会这样写:

原始写法

package methodreferences;

import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;

public class Main
{

    static class PersonAgeComparator implements Comparator<Person> {
        public int compare(Person a, Person b) {
            return a.getBirthday().compareTo(b.getBirthday());
        }
    }

    public static void main(String[] args)
    {
        Person[] pArr = new Person[]{
            new Person("003", LocalDate.of(2016,9,1)),
            new Person("001", LocalDate.of(2016,2,1)),
            new Person("002", LocalDate.of(2016,3,1)),
            new Person("004", LocalDate.of(2016,12,1))};

        Arrays.sort(pArr, new PersonAgeComparator());

        System.out.println(Arrays.asList(pArr));
    }
}

其中,Arrays类的sort方法定义如下:

public static <T> void sort(T[] a, Comparator<? super T> c)

这里,我们首先要注意Comparator接口是一个函数式接口,因此我们可以使用Lambda表达式,而不需要定义一个实现Comparator接口的类,并创建它的实例对象,传给sort方法。

使用Lambda表达式,我们可以这样写:

改进一,使用Lambda表达式,未调用已存在的方法

package methodreferences;

import java.time.LocalDate;
import java.util.Arrays;

public class Main
{

    public static void main(String[] args)
    {
        Person[] pArr = new Person[]{
            new Person("003", LocalDate.of(2016,9,1)),
            new Person("001", LocalDate.of(2016,2,1)),
            new Person("002", LocalDate.of(2016,3,1)),
            new Person("004", LocalDate.of(2016,12,1))};

        Arrays.sort(pArr, (Person a, Person b) -> {
            return a.getBirthday().compareTo(b.getBirthday());
        });

        System.out.println(Arrays.asList(pArr));
    }
}

然而,在以上代码中,关于两个人生日的比较方法在Person类中已经定义了,因此,我们可以直接使用已存在的Person.compareByAge方法。

改进二,使用Lambda表达式,调用已存在的方法

package methodreferences;

import java.time.LocalDate;
import java.util.Arrays;

public class Main
{

    public static void main(String[] args)
    {
        Person[] pArr = new Person[]{
            new Person("003", LocalDate.of(2016,9,1)),
            new Person("001", LocalDate.of(2016,2,1)),
            new Person("002", LocalDate.of(2016,3,1)),
            new Person("004", LocalDate.of(2016,12,1))};

        Arrays.sort(pArr, (a, b) -> Person.compareByAge(a, b));

        System.out.println(Arrays.asList(pArr));
    }
}

因为这个Lambda表达式调用了一个已存在的方法,因此,我们可以直接使用方法引用来替代这个Lambda表达式,

改进二,使用方法引用

package methodreferences;

import java.time.LocalDate;
import java.util.Arrays;

public class Main
{

    public static void main(String[] args)
    {
        Person[] pArr = new Person[]{
            new Person("003", LocalDate.of(2016,9,1)),
            new Person("001", LocalDate.of(2016,2,1)),
            new Person("002", LocalDate.of(2016,3,1)),
            new Person("004", LocalDate.of(2016,12,1))};

        Arrays.sort(pArr, Person::compareByAge);

        System.out.println(Arrays.asList(pArr));
    }
}

在以上代码中,方法引用Person::compareByAge在语义上与Lambda表达式 (a, b) -> Person.compareByAge(a, b) 是等同的,都有如下特性:

  • 真实的参数是拷贝自Comparator<Person>.compare方法,即(Person, Person);
  • 表达式体调用Person.compareByAge方法;

四种方法引用类型

静态方法引用

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

特定实例对象的方法引用

如下示例,引用的方法是myComparisonProvider 对象的compareByName方法;

        class ComparisonProvider
        {
            public int compareByName(Person a, Person b)
            {
                return a.getName().compareTo(b.getName());
            }

            public int compareByAge(Person a, Person b)
            {
                return a.getBirthday().compareTo(b.getBirthday());
            }
        }
        ComparisonProvider myComparisonProvider = new ComparisonProvider();
        Arrays.sort(rosterAsArray, myComparisonProvider::compareByName);

任意对象(属于同一个类)的实例方法引用

如下示例,这里引用的是字符串数组中任意一个对象的compareToIgnoreCase方法。

        String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
        Arrays.sort(stringArray, String::compareToIgnoreCase);

构造方法引用

如下示例,这里使用了关键字new,创建了一个包含Person元素的集合。

Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
transferElements方法的定义如下,功能为集合拷贝,
public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>>
    DEST transferElements(
        SOURCE sourceCollection,
        Supplier<DEST> collectionFactory) {

        DEST result = collectionFactory.get();
        for (T t : sourceCollection) {
            result.add(t);
        }
        return result;
}

什么场景适合使用方法引用

当一个Lambda表达式调用了一个已存在的方法

什么场景不适合使用方法引用

当我们需要往引用的方法传其它参数的时候,不适合,如下示例:

IsReferable demo = () -> ReferenceDemo.commonMethod("Argument in method.");

参考资料

http://java8.in/java-8-method-references/

https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

时间: 2024-12-15 18:05:28

JAVA 8 方法引用 - Method References的相关文章

浅谈Java 8中的方法引用(Method References)

本人接触Java 8的时间不长,对Java 8的一些新特性略有所知.Java 8引入了一些新的编程概念,比如经常用到的 lambda表达式.Stream.Optional以及Function等,让人耳目一新.这些功能其实上手并不是很难,根据别人的代码抄过来改一下,并不要知道内部的实现原理,也可以很熟练地用好这些功能.但是当我深究其中一些细节时,会发现有一些知识的盲区.下面我就来谈一下Java 8中的Method References这个概念. 首先我给出官方对于这一概念的详细解释,https:/

Java 8Lambda之方法引用(Method References)

方法引用分为4类,方法引用也受到访问控制权限的限制,可以通过在引用位置是否能够调用被引用方法来判断.具体分类信息如下: 类型 使用方式 静态方法 ContainingClass::staticMethodName 指定实例的方法 containingObject::instanceMethodName 特定类实例的任意方法 ContainingType::methodName 构造方法 ClassName::new 引用静态方法 ContainingClass::staticMethodName

java 8 方法引用(method references)

1 什么是方法引用(method references) java 8 添加了一个很熟悉但是又很陌生的符号::. 你也许会看到这样的代码 System.out::println 其实就是方法引用(method references).由于java 8 把方法/函数也作为第一输入参数.所以你会看到inventory.comparing(Apple::getWeight);这样"奇怪"的代码. 2 如何使用方法引用(method references) 其实方法引用是lambda 表达式的

Upgrading to Java 8——第二章 Method References(方法引用)

概述 很多java 方法 会使用函数式接口作为参数.例如,java.util.Arrays类中的一个sort方法,就接受一个Comparator接口,它就是一个函数式接口,sort方法的签名如下: public static T[] sort(T[] array, Comparator<? super T> comparator) 相对于传递一个Compartor的实例给sort方法,不如传递一个Lambda表达式. 进一步,我们可以传递一个方法引用来代替Lambda表达式,一个简单的方法引用

Java 8 方法引用

There are four kinds of method references: Kind Example Reference to a static method ContainingClass::staticMethodName Reference to an instance method of a particular object containingObject::instanceMethodName Reference to an instance method of an a

Java 之 方法引用

方法引用 一.冗余的Lambda场景 来看一个简单的函数式接口以应用Lambda表达式: 1 @FunctionalInterface 2 public interface Printable { 3 void print(String str); 4 } 在 Printable 接口当中唯一的抽象方法 print 接收一个字符串参数,目的就是为了打印显示它.那么通过Lambda来使用它的代码很简单: 1 public class Demo01PrintSimple { 2 private st

Java8之方法引用

一.概述 在学习lambda表达式之后,我们通常使用lambda表达式来创建匿名方法.然而,有时候我们仅仅是调用了一个已存在的方法.如下: Arrays.sort(stringsArray,(s1,s2)->s1.compareToIgnoreCase(s2)); 在Java8中,我们可以直接通过方法引用来简写lambda表达式中已经存在的方法. Arrays.sort(stringsArray, String::compareToIgnoreCase); 这种特性就叫做方法引用(Method

jdk1.8新特性Lambda表达式方法引用

前言 在之前我们接触了JDK1.8引入的新特新lambda表达式没在某种程度上,它可以简化我们的代码,帮助我们快速的编写代码,但在这其中我们之前的编写方式并不是lambda表达式最简洁的方式,而在头屑情况下我们可以使用lambda表达式的方法引用是代码进一步简洁化. 一.方法引用: 在java中方法引用主要是用来替代lambda表达式进一步简化代码,方法引用符号的写法是两个冒号“::”,其中方法引用的用法有一下几种. 1.对象名称::成员方法 如果一个对象中有一个成员方法,就好就是lambda表

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

最近看了一下java 8的一些新特性,其中最重要的莫过于Lambda表达式了,通过一阵子的学习,原本准备自己写一篇博客的,后来阅读了一位学长翻译过来的博客(原文是Brain Goetz的State of Lambda,下面会给出原文链接),觉得写的十分完美,把我想要写的和我没想到的都罗列了出来,就把这个分享给大家了. 注:原译文见  http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 英语原版见:http://cr.