程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> JAVA 8 方法引用,java方法引用

JAVA 8 方法引用,java方法引用

編輯:JAVA綜合教程

JAVA 8 方法引用,java方法引用


什麼是方法引用

  簡單地說,就是一個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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved