zoukankan      html  css  js  c++  java
  • JAVA 8 方法引用

    什么是方法引用

      简单地说,就是一个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

  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/chenpi/p/5885706.html
Copyright © 2011-2022 走看看