美文网首页JAVA基础
Java基础 - 方法引用

Java基础 - 方法引用

作者: HRocky | 来源:发表于2019-05-15 15:52 被阅读0次

    原文链接:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

    你可以使用lambda表达式来创建匿名方法。然而,有时lambda表达式什么都不做,而是调用现有方法。在这些情况下,通过名称来引用一个已经存在的方法会更清晰。方法引用使您能够做到这一点;对于已经有名称的方法,方法引用是紧凑的、易于阅读的lambda表达式。

    考虑有下面的一个Person类:

    public class Person {
    
        public enum Sex {
            MALE, FEMALE
        }
    
        String name;
        LocalDate birthday;
        Sex gender;
        String emailAddress;
    
        public int getAge() {
            // ...
        }
    
        public Calendar getBirthday() {
            return birthday;
        }    
    
        public static int compareByAge(Person a, Person b) {
            return a.birthday.compareTo(b.birthday);
        }
    }
    

    假设您的社交网络应用程序的成员包含在一个数组中,并且希望按年龄对数组进行排序。你可以使用下面的代码:

    Person[] rosterAsArray = roster.toArray(new Person[roster.size()]);
    
    class PersonAgeComparator implements Comparator<Person> {
        public int compare(Person a, Person b) {
            return a.getBirthday().compareTo(b.getBirthday());
        }
    }
            
    Arrays.sort(rosterAsArray, new PersonAgeComparator());
    

    此排序调用的方法签名如下:

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

    注意Comparator接口是一个函数接口。因此,您可以使用lambda表达式,而不是定义并创建实现Comparator的新实例:

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

    但是,比较两个Person实例的出生日期的方法已经以Person.compareByage的形式存在。您可以在lambda表达式的主体中调用此方法:

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

    因为这个lambda表达式调用一个现有的方法,所以可以使用方法引用而不是lambda表达式:

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

    方法引用Person::compareByAge和lambda表达式(a,b)->Person.compareByAge(a,b)有一样的语义。它们两者都有下列特征:

    • Its formal parameter list is copied from Comparator<Person>.compare, which is (Person, Person).
    • Its body calls the method Person.compareByAge.

    方法引用种类

    有4种种类的方法引用:

    种类 示例
    对静态方法的引用 ContainingClass::staticMethodName
    对特定对象的实例方法的引用 containingObject::instanceMethodName
    对特定类型的任意对象的实例方法的引用 ContainingType::methodName
    对构造方法的引用 ClassName::new

    对静态方法的引用

    Person::compareByAge是对静态方法的引用。

    对特定对象的实例方法的引用

    以下是对特定对象的实例方法的引用的示例:

    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);
    

    方法引用mycompisonProvider:compareByName调用的compareByNam方法是mycompisonProvider对象的一部分。JRE推断方法类型参数,在本例中是(Person,Person)。

    对特定类型的任意对象的实例方法的引用

    以下是对特定类型的任意对象的实例方法的引用的示例:

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

    与方法引用String::compareToIgnoreCase等效的lambda表达式有(String a, String b)这样的参数列表,a和b是任意的的名称。方法引用会调用方法a.compareToIgnore(b)。

    对构造方法的引用

    通过使用名称new,你可以像静态方法引用那样引用构造方法。以下方法将元素从一个集合复制到另一个集合:

    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;
    }
    

    函数接口Supplier包含一个返回一个对象的无参方法get。因此,你可以使用像下面一样使用lambda表达式来调用transferElements方法:

    Set<Person> rosterSetLambda = transferElements(roster, () -> { return new HashSet<>(); });
    

    可以使用构造函数引用代替lambda表达式,如下所示:

    Set<Person> rosterSet = transferElements(roster, HashSet::new);
    

    Java编译器推断要创建包含Person类型元素的HashSet集合。或者,您可以像下面一样指定:

    Set<Person> rosterSet = transferElements(roster, HashSet<Person>::new);
    

    相关文章

      网友评论

        本文标题:Java基础 - 方法引用

        本文链接:https://www.haomeiwen.com/subject/bvipaqtx.html