forEach是jdk8中Iterable新增的方法,源碼如下:
/ * @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
而List間接繼承了Iterable,所以List也有forEach這個默認方法。從源碼可以看出,參數是一個Consumer類型的接口,forEach方法就是接收一個參數爲Consumer類型,然後執行自己內部實現的for循環方法。
在8之前,可以這樣
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Consumer<Integer> c=new Consumer<Integer>(){
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
};
list.forEach(c);
也可以使用匿名內部類的方式,匿名內部類實際會新生成xxx$1.class文件,並不是說可以new一個接口。
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);
}
});
jkd8後,我們不僅可以使用匿名內部類作爲參數,也可以使用函數式接口作爲參數:
函數式接口有以下三種類型,
1.lambda表達式
2.方法引用
3.構造方法引用
我們先來驗證第一種函數式接口類型lambda表達式。
具體的lambda的簡寫代碼方式,我這邊就不講解了。lambda的作用就是一個是簡寫代碼,另一個就是現在講的作爲函數式接口的類型。,Lambda表達式是對象,它們必須依附於一類特別的對象類型——函數式接口(Functional Interface)。什麼是函數式接口呢?如果一個接口中,有且只有一個抽象的方法(Object類中的方法不包括在內),那這個接口就可以被看做是函數式接口。
所以上面的代碼如果改成傳參是lambda表達式,
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
list.forEach(i->System.out.println(i));
接下來是方法引用,其實就是傳一個方法過去。:方法引用
方法引用的語法是 對象::方法名(只是其中一種)
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::print);
}
public static void print(int i){
System.out.println(i);
}
}
最後我們來看下創建函數式接口的最後一種,第三種方式:構造方法引用 ,繼續改程序
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);
}
}