在使用forEach遍历ArrayList集合时遇到一种高大上的写法,那就是使用“System.out::println”作为参数传入到forEach方法中。进入到forEach方法源码中可以发现,forEach方法的参数类型是ConSumer接口,不禁感到十分的困扰。
通过以下例子,希望能够帮助到大家去理解该写法。
该例子使用到概念有:局部内部类,匿名内部类,函数式接口,lambda表达式。
在看完接口 A ,类B 和 类BB后将注意力集中在11行到第19行。
首先大家知道BB作为接口A的实现类是需要重写接口A的set方法,此时如果想要创建一个 实现接口A 并且 只想使用一次的类可以怎么办 ?那么我们就可以通过匿名内部类的方式创建一个没有类名的对象并赋给引用aaa (匿名内部类多用于方法,比如某个方法的参数是一个接口类型,此时我们可以通过匿名内部类的方式创建一个没有名字的对象作为参数传递给方法) ,此时接口A因为只有一个抽象方法,所以接口A是一个函数式接口,而lambda表达式(也就是第18行等号右边的式子)可以用于替换成第12行等号右边的式子。此时要注意到因为lambda中的 B.printSer( ) 相当于是被重写的set方法的方法体中的内容并且只有这一个代码,所以最终我们可以用第19行中双冒号的方式来替换lambda表达式,而 B::printSer 这种写法意思就是引用了类B的printSer这个方法,因为printSerr方法是static修饰的所以可以这样写,不然就得 new B( )::printSer。
总的来说 B::printSer 可以等价于一个实现了接口A的类的对象 并且重写了接口A的唯一方法,且被重写的方法的方法体中只有 B.printSer()这一行。
注意:匿名内部不仅可以new 一个接口,还可以new 一个抽象类。
以上内容为个人理解
欢迎各位大佬批评指正