上一篇文章中,咱們簡單介紹了Java8的Lambda表達式以及函數式接口的概念,接下來咱們繼續深刻Java8函數式編程模型。編程
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); list.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } }); } }
這段程序很簡單,首先初始化一個Integer類型的集合而後向控制檯輸出每一個元素。其中咱們注意到forEach方法,它就是Java8中新增長的默認方法。segmentfault
public interface Iterable<T> { . .省略 . default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } }
它被聲明在Iterable接口中,並被關鍵字default修飾。這樣任何一個該接口的子類型均可以繼承forEach方法的實現,因此List接口由於是Iterable的間接子接口,因此也繼承了該默認方法。Java8採用這種巧妙的方式既擴展了接口的功能,又兼容了老版本。ide
接下來分析下forEach的實現,首先接收了一個Consumer類型的參數action,進行非空判斷,而後遍歷當前全部元素交由action的accept方法進行處理。那麼Consumer又是什麼鬼,看源碼函數式編程
@FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); . .省略 . }
一個接口,有且僅有一個抽象方法,被@FunctionalInterface修飾,典型的函數式接口。
ok,如今咱們知道forEach接收的Consumer類型的參數是一個函數式接口,接口裏惟一的accept抽象方法接收一個參數,不返回值。那經過上一篇文章咱們知道,建立函數式接口類型的實例其中一種方式是使用Lambda表達式,因此能夠將最上面的程序改造一下函數
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //Lambda表達式 接收一個參數 不返回值 list.forEach(item -> System.out.println(item)); } }
該lambda表達式item -> System.out.println(item)接收一個參數 不返回值,符合accept方法定義,編譯經過。
也就是說若是使用lambda表達式來建立一個函數式接口實例,那這個lambda表達式的入參和返回必須符合這個函數式接口中惟一的抽象方法的定義。ui
接下來再對程序進行改造this
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //方法引用 list.forEach(System.out::println); } }
看到out後面有兩個冒號,反正當時我是凌亂了。。。這個就是函數式接口實例第二種建立方式:方法引用
方法引用的語法是 對象::方法名(只是其中一種)
一樣,使用方法引用方式去建立函數式接口實例也必須遵照方法的定義,看下此處println方法源碼code
public void println(Object x) { String s = String.valueOf(x); synchronized (this) { print(s); newLine(); } }
接收一個參數,並不返回值,編譯經過。
最後咱們來看下建立函數式接口的最後一種,第三種方式:構造方法引用 ,繼續改程序orm
public class Test1 { public static void main(String[] args) { List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); //構造方法引用 list.forEach(Test1::new); } Test1(Integer i){ System.out.println(i); } }
構造方法引用的語法是:類名::new
咱們給Test1新添加了一個構造方法,該構造方法接收一個參數,不返回值,編譯經過。(僅爲展現構造方法引用的用法)對象
結合上一篇文章能夠總結一下,建立函數式接口類型的三種方式:
1.lambda表達式
2.方法引用
3.構造方法引用
注意:不管是哪一種方式,必需要符合抽象方法的方法定義
小結:本篇咱們首先介紹了接口中的默認方法,而後又分別用幾段程序代碼展現了方法引用和構造方法引用的使用方式,後續還會提供一些示例來加深理解,若是以爲本篇文章對你有所幫助幫忙贊一下哈。