網頁

2018/8/27

Java 8 Method References(方法參考/方法引用)的使用時機

Java 8加入了lambda表示式(lambda expression)的語法特性,而lambda表示式可以進一步改用method references(方法參考/方法引用)的寫法。所以使用method references前你應該知道lambda語法該如何使用。

Method references即使可以進一步簡化Lambda語法,但仍有使用上的限制。

只有當lambda中僅執行一個方法的情況下才能改以method references語法來撰寫。

例如下面的List.forEach(Consumer action)分別使用匿名類別,lambda及method reference的方式來印出每個元素字串。

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class Main {

    public static void main(String[] args) {
        
        List<String> strList = Arrays.asList("A","B","C");
    
        // Anonymous class (匿名類別)
        strList.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s); // ABC
            }
        });
        
        // Lambda expression
        strList.forEach(s -> System.out.print(s)); // ABC
        
        // Method reference(方法參考)
        strList.forEach(System.out::print); // ABC

        // Method reference(方法參考) 使用靜態方法
        strList.forEach(Main::static_printList); // ABC

        // Method reference(方法參考) 使用實例方法
        Main main = new Main();
        strList.forEach(main::instance_printList); // ABC

    }

    private static void static_printList(String s) {
        System.out.print(s);
    }

    private void instance_printList(String s) {
        System.out.print(s);
    }
    
}

上例中因為lambda中僅執行了System.outprintln()一個方法,因此才能以method references來改寫。

且傳入lambda的參數必須同樣是lambda中被執行方法的引數。例如上面lambda的參數為s,且剛好做為println()方法的引數。

strList.forEach(s -> System.out.print(s)); // lambda
strList.forEach(     System.out::print  ); // method reference

下面是另一個範例,把接收兩個參數的Functional interface (Comparator.compare(T o1, T o2))的lambda語法改寫為method reference。

import java.util.Arrays;
import java.util.Comparator;

public class Main {

    public static void main(String[] args) throws Exception {

        String[] stringArray = { "C", "D", "A", "E", "B" };
        // 匿名類別
        Arrays.sort(stringArray, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }});
        // Lambda expression
        Arrays.sort(stringArray, (s1, s2) -> s1.compareToIgnoreCase(s2));
        // Method reference
        Arrays.sort(stringArray, String::compareToIgnoreCase);
          
    }
    
}

不過Method references是語法糖的一種,而使用上卻不是那麼直覺,因為你必須知道被呼叫的方法傳入的引數型態及數目及傳入lambda的參數也是相同的型態及數目。且有使用上的限制,還是覺得寫lambda就好了,不需免強一定要使用method references來寫。


參考:

沒有留言:

張貼留言