美文网首页
java8 之方法引用

java8 之方法引用

作者: bern85 | 来源:发表于2019-07-29 15:29 被阅读0次

    方法引用

    你可以使用lambda表达式来创建匿名方法。 但是,有时,lambda表达式只是仅仅调用一个方法。在这些情况下,通过方法名称调用现有方法会更清楚得表达意思。java8得方法引用现在允许你这样做,对于已有名称的方法,方法引用是紧凑的,易于阅读的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得数组,你希望通过年龄Age来排序,代码请参考MethodReferencesTest

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

    方法sort的方法签名如下:

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

    我们发现Comparator一个 functional interface接口,因此,我们应该使用lambda表达式,而不是定义然后创建实现Comparator的接口的新实例。

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

    但是,这种比较两个Person实例的birthday的方法,我们已经在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)相同.

    方法引用得种类

    方法引用主要有四类。

    种类 格式 例子
    指向静态方法得方法引用 ContainingClass::staticMethodName Integer::parseInt
    指向任意类型实例方法得方法引用 ContainingType::methodName String::length
    指向现有对象的实例方法得方法引用 containingObject::instanceMethodName person::getEmailAddress
    指向构造函数 ClassName::new Person::new

    指向静态方法得方法引用

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

    指向任意类型实例方法得方法引用

    引用示例:

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

    方法引用 String::compareToIgnoreCase 等效的lambda表示式为:

    (String a,String b)-> a.compareToIgnoreCase(b)
      Arrays.sort(stringArray, (a, b) -> {
            return Person.compareByAge(a, b);
        });
    

    指向现有对象的实例方法得方法引用

    引用示例:

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

    方法引用myComparisonProvider::compareByName调用实例myComparisonProvider方法compareByName。 因此JRE推断出方法类型参数是(Person,Person)。

    指向构造函数

    引用示例:

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

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

    相关文章

      网友评论

          本文标题:java8 之方法引用

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