Java8中方法引用的使用詳解
1. 引言
Java8中最受廣大開發中喜歡的變化之一是因為引入了 lambda 表示式,因為這些表示式允許我們放棄匿名類,從而大大減少了樣板程式碼,並提高了可讀性。
方法引用是lambda表示式的一種特殊型別。它們通常通過引用現有方法來建立簡單的lambda表示式。
方法引用包括以下四種類型:
- 靜態方法
- 特定物件的例項方法
- 特定型別的任意物件的例項方法
- 構造方法
- 在本篇文章中,我們將探討Java中的方法引用。
2. 引用靜態方法
We'll begin with a very simple example,capitalizing and printing a list of Strings:
我們從一個非常簡單的示例開始,字串轉成大寫並列印:
List<String> messages = Arrays.asList("hello","baeldung","readers!");
我們可以通過簡單的lambda表示式直接呼叫 StringUtils.capitalize() 方法:
messages.forEach(word -> StringUtils.capitalize(word));
或者,我們可以使用方法引用來簡單地引用 capitalize 靜態方法:
messages.forEach(StringUtils::capitalize);
注意,方法引用應使用::運算子。
3. 引用特定物件的例項方法
為了演示這種型別的方法引用,我們新建以下這兩個類:
public class Bicycle { private String brand; private Integer frameSize; // standard constructor,getters and setters } public class BicycleComparator implements Comparator { @Override public int compare(Bicycle a,Bicycle b) { return a.getFrameSize().compareTo(b.getFrameSize()); } }
建立一個 BicycleComparator 物件來比較自行車尺寸:
BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
我們可以使用lambda表示式按尺寸大小對自行車進行排序,但需要指定兩個自行車例項進行比較:
createBicyclesList().stream() .sorted((a,b) -> bikeFrameSizeComparator.compare(a,b));
我們可以使用方法引用讓編譯器把控制代碼引數傳遞給我們:
createBicyclesList().stream() .sorted(bikeFrameSizeComparator::compare);
4. 引用特定型別任意物件的例項方法
這種型別的方法引用與前面的示例類似,但不必建立自定義物件來執行比較。
讓我們建立一個要排序的Integer 整數列表:
List<Integer> numbers = Arrays.asList(5,3,50,24,40,2,9,18);
如果我們使用經典的 lambda 表示式,這兩個引數都需要顯式傳遞,而使用方法引用則要簡單得多:
numbers.stream() .sorted((a,b) -> a.compareTo(b)); numbers.stream() .sorted(Integer::compareTo);
儘管它仍然是一行程式碼,但是方法引用更容易閱讀和理解。
5. 引用建構函式
我們可以像在第一個例子中引用靜態方法一樣引用建構函式。唯一區別是需要使用new關鍵字。
現在我們用不同品牌的String列表建立一個Bicycle陣列:
List<String> bikeBrands = Arrays.asList("Giant","Scott","Trek","GT");
首先,我們將向Bicycle類新增一個新的建構函式:
public Bicycle(String brand) { this.brand = brand; this.frameSize = 0; }
接下來,我們將使用方法引用中的新建構函式,並從原始的String列表中生成一個Bicycle陣列:
bikeBrands.stream() .map(Bicycle::new) .toArray(Bicycle[]::new);
注意如何使用方法引用呼叫Bicycle和Array建構函式,從而使程式碼看起來更加簡潔明瞭。
6. 其他示例和限制
目前為止,方法引用是一個使程式碼非常清晰和易讀的好方法。但是,我們不能用它們來代替各種lambda表示式,因為它們有一些侷限性。
它們的主要侷限性是由於它們最大的優點:前一個表示式的輸出需要與引用的方法宣告的輸入引數匹配。
看看這個限制的例子:
createBicyclesList().forEach(b -> System.out.printf( "Bike brand is '%s' and frame size is '%d'%n",b.getBrand(),b.getFrameSize()));
這個簡單的例子不能用方法引用來表示,因為在我們的例子中,printf 方法需要3個引數,而使用createBicyclesList().forEach()只允許方法引用一個引數(Bicycle物件)。
最後,我們研究下,如何建立一個可以從lambda表示式引用的no-operation函式。
在本例中,我們希望使用lambda表示式而不使用其引數。
首先,建立 doNothingAtAll 方法:
private static <T> void doNothingAtAll(Object... o) { }
因為這是一個varargs方法,它可執行在任意 lambda 表示式中,而不管引用的物件或引數的數量。我們看看它的作用:
createBicyclesList() .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));
7. 總結
在這篇文章中,我們學習了Java中的方法引用,以及如何使用它們來替換lambda表示式,從而提高了可讀性並闡明程式設計的意圖。
到此這篇關於Java 8 中的方法引用使用的文章就介紹到這了,更多相關Java8 方法引用內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!