Function,Consumer,Predicate,Supplier這些接口有一個共性,就是都有一個@FunctionalInterface的註解, 有了這個註解,你就能夠自定義lamda表達式了.html
本文先介紹一些例子,而後自定義一個lamda表達式的接口.java
先看一下Function接口定義:app
@FunctionalInterface public interface Function<T, R>
接口接受兩個泛型類型<T, R>.異步
再看一下接口定義的方法(非靜態,非default), 支持lamda表達式的接口只容許定義一個抽象方法(@FunctionalInterface註解的接口,只容許定義一個抽象方法),只要記住這一點,你就不會弄混了..net
R apply(T t); /** * T 入參類型, t 輸入參數 * R 返回值類型 */
OK, 如今明確了, 該接口的lamda表達式應該是接受一個入參,最後要有一個返回值, 寫法應該是這樣的: (x) -> {return y;} 線程
若是你的lamda表達式很是簡單,只有一行,那麼你能夠不寫return, 不加花括號{}, 返回值後面能夠不加分號.code
下面就能夠寫example了, 寫一個簡單的, 再寫一個標準的.htm
public void testFunction(){ //簡單的,只有一行 Function<Integer, String> function1 = (x) -> "test result: " + x; //標準的,有花括號, return, 分號. Function<String, String> function2 = (x) -> { return "after function1"; }; System.out.println(function1.apply(6)); System.out.println(function1.andThen(function2).apply(6)); }
OK, Function的例子寫完了,接下來寫其餘的,其實原理懂了,其餘的就都簡單了,而後就是熟能生巧了.blog
再看看Supplier的接口定義,這個接口定義比較簡單,我就都貼上來了接口
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
接口接受一個泛型<T>, 接口方法是一個無參數的方法, 有一個類型爲T的返回值. OK, 那麼接口的lamda表達式應該是這樣的: () -> { return something; }, 好,下面來寫一個example.
public void testSupplier(){ //簡寫 Supplier<String> supplier1 = () -> "Test supplier"; System.out.println(supplier1.get()); //標準格式 Supplier<Integer> supplier2 = () -> { return 20; }; System.out.println(supplier2.get() instanceof Integer); }
到這裏你或許有一點疑惑, 這Supplier到底能用在哪啊? Java 8裏新增了一個異步線程的類,很牛逼,很強大的類: CompletableFuture, 裏面的不少方法的入參都用到的Supplier, 例如: supplyAsync方法. 本文暫時不介紹CompletableFuture.
接下來是Consumer, 咱們來看一下接口的定義:
@FunctionalInterface public interface Consumer<T>
而後再看一下里面的抽象方法:
void accept(T t);
如今瞭解了: 接口接受一個泛型<T>, 接口方法是入參類型爲T, 無返回值的方法, OK,下面開始寫example:
public void testConsumer(){ Consumer<String> consumer1 = (x) -> System.out.print(x); Consumer<String> consumer2 = (x) -> { System.out.println(" after consumer 1"); }; consumer1.andThen(consumer2).accept("test consumer1"); }
接下來看一下Predicate接口
接口定義:
@FunctionalInterface public interface Predicate<T>
抽象方法:
boolean test(T t);
接口接受一個泛型<T>, 接口方法的入參類型是T, 返回值是一個布爾值, OK, 下面寫example:
public void testPredicate(){ Predicate<String> predicate = (x) -> x.length() > 0; System.out.println(predicate.test("String")); }
Predicate接口在stream裏面用的比較多, 感興趣的能夠去看看stream, java 8 裏另外一個新的東西,很好玩.
到這裏基本明白這些lamda表達式的接口怎麼用了,接下來自定義一個支持lamda表達式的接口玩玩,
@FunctionalInterface public interface CustomLamda<T> { T testCustomFunction(Consumer<T> cunsumer); /*若是把下面方法的註釋放開, 那麼接口就報錯了. 驗證了前面所說的:@FunctionalInterface註解的接口只容許 *有一個抽象方法 */ //T anErrorMethod(); }
下面是實現:
public void testCustomLamda(){ Consumer<String> consumer = (x) -> { System.out.println("test" + x); }; CustomLamda<String> customLamda = (x) -> { x.accept("6"); return "6"; }; customLamda.testCustomFunction(consumer); }
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { int i = 1/0; return 100; });
參考博文: