Java8中最受廣大開發中喜歡的變化之一是由於引入了 lambda 表達式,由於這些表達式容許咱們放棄匿名類,從而大大減小了樣板代碼,並提升了可讀性。
方法引用是lambda表達式的一種特殊類型。它們一般經過引用現有方法來建立簡單的lambda表達式。java
方法引用包括如下四種類型:編程
在本篇文章中,咱們將探討Java中的方法引用。api
We'll begin with a very simple example, capitalizing and printing a list of Strings:數組
咱們從一個很是簡單的示例開始,字符串轉成大寫並打印:ide
List<String> messages = Arrays.asList("hello", "baeldung", "readers!");
咱們能夠經過簡單的lambda表達式直接調用 StringUtils.capitalize()
方法:函數
messages.forEach(word -> StringUtils.capitalize(word));
或者,咱們可使用方法引用來簡單地引用 capitalize
靜態方法:學習
messages.forEach(StringUtils::capitalize);
注意,方法引用應使用::
運算符。this
爲了演示這種類型的方法引用,咱們新建如下這兩個類:code
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);
這種類型的方法引用與前面的示例相似,但沒必要建立自定義對象來執行比較。
讓咱們建立一個要排序的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);
儘管它仍然是一行代碼,可是方法引用更容易閱讀和理解。
咱們能夠像在第一個例子中引用靜態方法同樣引用構造函數。惟一區別是須要使用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構造函數,從而使代碼看起來更加簡潔明瞭。
目前爲止,方法引用是一個使代碼很是清晰和易讀的好方法。可是,咱們不能用它們來代替各類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));
在這篇文章中,咱們學習了Java中的方法引用,以及如何使用它們來替換lambda表達式,從而提升了可讀性並闡明編程的意圖。
若是你以爲文章還不錯,記得關注公衆號: 鍋外的大佬
鍋外的大佬博客