1.函數方法

如果接口只有一個方法,則可以為該接口類型的變量分配一個由lambda 表達式(lambda 函數)給出的值。這樣的接口被稱為功能接口(在 Java 添加對 lambda 函數的支持之後)。

例如,Java 有Consumer<Type>接口,接口有accept(Type obj)方法。為什麼需要這個接口?

在 Java 8 中,集合有一個forEach()方法,可以讓你集合中的每個元素執行一些操作 。這裡的功能接口用於將操作傳遞給方法。 Consumer<T>forEach()

以下是顯示集合所有元素方法:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach( (s) -> System.out.println(s) );
顯示集合的所有元素(使用 lambda 表達式)

編譯器會將上面的代碼轉換為下面的代碼:

ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "Hello", "how's", "life?");

list.forEach(new Consumer<String>()
{
   public void accept(String s)
   {
      System.out.println(s));
   }
});
顯示集合的所有元素(使用匿名類)

第一個版本肯定比第二個版本短。雖然帶有 lambda 表達式的代碼難以閱讀,但帶有匿名內部類的代碼有時更難閱讀。



2、方法參考

然而,我們的lambda 表達式代碼可以寫得更短。

首先,您可以省略參數周圍的括號s

list.forEach( (s) -> System.out.println(s) );
list.forEach( s -> System.out.println(s) );

這只有在只有一個參數的情況下才能完成。如果有多個參數,則必須使用括號

其次,你可以這樣寫:

list.forEach( System.out::println );
最緊湊的符號

這是完全相同的符號。請注意,在 . 之後沒有括號println

這裡我們有相同的代碼——一個方法調用:

object::method
x -> object.method(x)

想一想:我們想對list集合中的每個元素執行一些操作。如果操作是單個函數調用(例如println()),那麼將函數作為參數簡單地傳遞給方法是有意義的。

但是我們如何向編譯器解釋我們要傳遞方法而不是調用它呢?為此,我們在方法名稱前使用了兩個冒號,而不是點運算符。單個冒號已用於指示三元運算符。

這是最簡單和最緊湊的表示法。



3.構造函數

當我們使用 I/O 流時,使用雙冒號的方法引用非常方便。稍後你會看到這個。

同時,讓我們談談傳遞方法引用的 3 種流行方式:

引用對象的方法

要傳遞對對象方法的引用,您需要編寫類似. 此代碼等效於.object::method
x -> object.method(x)

特殊thissuper變量可以用作對象。

引用類的方法

要傳遞對靜態方法的引用,您需要編寫類似. 此代碼被轉換為類似的代碼class::methodx -> class.method(x);

引用構造函數

構造函數的行為類似於靜態類方法,因此您也可以將引用傳遞給構造函數。這是它的樣子:class::new

例如,您可以繞過集合的類型擦除並將方法傳遞toArray()給將創建所需數組的構造函數的引用:toArray(int[]::new);