list 的forEach 方法 使用lambda 和“”::”关键字

 你是否会疑惑  list  遍历的时候 就这么一行是怎么做到的如此神奇?

 List<String> al = Arrays.asList("a", "b", "c", "d");
        al.forEach(System.out::println);  //神奇连元素我都没传进来怎么做到遍历的??

从源码上分析:

      点击进入方法源码:

       可以看到,此方法来自顶级接口Iterable  ,forEach  方法体中   for(T t: this) 这显然是在遍历我们每一个元素呀!所以我们现在弄清楚    for循环中   action.accept(t)   对我们list 中的每个元素干了啥,!!

首先从入参开始分析

              1 forEach 方法入参规定:Consumer<? super T> action
               2 Consumer  接口是功能接口,是被@FunctionalInterface  标注的 这个接口的模板是消费的意思,传参返回空代表消费 ,accept方法, 只要调用的方法[这里说的方法是指,System.out.println(String x),你看这个方法是不是符合 Consumer 接口待实现的方法 void accept(T t);  的模板样式,都是入参并且返回void,]符合待实现方法accept模板就可以,并且  :: 代表调用某个类的静态方法  ,意思是调用的方法被作为 Consumer 接口的实现, 这里还要知道注解@FunctionalInterface保证了接口有且仅有一个抽象方法,所以jdk能匹配到相应的 方法。
            3 还要知道  forEach 入参的类型是  Consumer   和 使用::  关键字后直接给转成对应的Consumer接口类型了(我猜测)

总结 : forEach 正常思维应该输入Consumer的接口实例,然后在写具体的待实现方法,但是我直接把待实现的方法具体传过去
        等于说我不是在传参,而是传递一种行为,传递一个函数!!而且System.out::println 就是在调用一个方法 调用System.out.println(String x),所以就是System.out.println(String x) 方法作 为参数传递给forEach,而由于Consumer  只有一个待实现的方法,所以jdk 知道这个函数一定是传给唯一的待实现方法的具体实现。

 


public class MyTest {
    public static void printValur(String str) {
        System.out.println("print value : " + str);
    }

    public static void main(String[] args) {
        List<String> al = Arrays.asList("a", "b", "c", "d");
        al.forEach(System.out::println);//==========与下面等同=================

        //==========与下面等同=================
        System.out.println("===================================");
        for (String a : al) {
            MyTest.printValur(a);
        }

      /*  解释:1 forEach 方法是list的顶级接口的Iterable 接口定义的方法,入参规定:Consumer<? super T> action
               2 Consumer  接口是功能接口,是被@FunctionalInterface  标注的 这个接口的模板是消费的意思,传参返回空代表消费 ,accept方法
              3 只要调用的方法[这里说的方法是指,printValur(String),你看这个方法是不是符合 Consumer 接口待实现的方法 void accept(T t);
                的模板样式,都是入参并且返回void
              ,]符合待实现方法accept模板就可以,并且  :: 代表调用某个类的静态方法  ,意思是调用的方法被作为 Consumer 接口的实现,
                   这里还要知道注解@FunctionalInterface保证了接口有且仅有一个抽象方法,所以jdk能匹配到相应的 方法
         4 还要知道  forEach 入参的类型是  Consumer   和 使用::  关键字后直接给转成对应的Consumer接口类型了(我猜测)
*/
        System.out.println("===================================");
        //  forEach 正常思维应该出入Consumer的接口实例,然后在写具体的待实现方法,但是我直接把待实现的方法具体传过去
        //等于说我不是在传参,而是传递一种行为,传递一个函数!!而且MyTest::printValur  就是在调用一个方法,所以就是方法作为参数传递给forEach,
        //而由于Consumer  只有一个待实现的方法,所以jdk 知道这个函数一定是传给唯一的待实现方法的具体实现。
        al.forEach(MyTest::printValur);


        //下面的方法和上面等价的=====================================


        Consumer<String> methodParam = MyTest::printValur; //方法参数


        // 1 lambda 表达式  也是对接口只有一个需要实现的方法 作用,  


        al.forEach(x -> methodParam.accept(x));//方法执行accept
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值