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) );
編譯器會將上面的代碼轉換為下面的代碼:
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)
特殊this
和super
變量可以用作對象。
引用類的方法
要傳遞對靜態方法的引用,您需要編寫類似. 此代碼被轉換為類似的代碼class::method
x -> class.method(x);
引用構造函數
構造函數的行為類似於靜態類方法,因此您也可以將引用傳遞給構造函數。這是它的樣子:class::new
例如,您可以繞過集合的類型擦除並將方法傳遞toArray()
給將創建所需數組的構造函數的引用:toArray(int[]::new);
GO TO FULL VERSION