java1.8出来好久一直没怎么关注。这段时间公司的项目数据处理,需要频繁操作集合,用for遍历集合做计算,感觉很费劲,而且有大量重复代码。可读性也不高。这时候想到java1.8新特性之一:函数式编程
一、函数式接口 (functional interface)
@FunctionalInterface 可以不用加该注解,编译的时候,对于只有一个抽象方法的接口,默认就是函数式接口。如果一个方法接受一个函数式接口作为参数,那么我们可以传入以下类型作为参数:
- 匿名内部类(Anonymous Inner Class)(Java的以前版本中经常使用的方式,在Java 8中不再被推荐)
- Lambda表达式
- 方法或者构造器的引用(Method or Constructor Reference
二、闭包(closure)(回顾)
lambda表达式大量用到了闭包和函数回调,java1.8之前不支持显性闭包,要实现代码片段的传递,只能通过内部类的方式,模拟闭包。
闭包简而言之就是 含有状态的函数。
比如一个二元函数 f _x,y,x,y是函数内部使用的变量,在只给定 一个参数 x = 7 的情况下, x 已经绑定,但是y还是*的,这个时候 f(7, y) 就相当于含有一个私有变量(x=7)的函数了。当再给定另外一个变量 y 的值就可对函数完整的求值。所以函数中 有的参数是绑定的,有的参数*的,这样的机制称为闭包。
闭包的价值在于可以作为函数对象或者匿名函数,持有上下文数据,作为第一级对象进行传递和保存。闭包中的部分变量没有在引用者的作用域内声明,对于引用者这些变量就是*变量。java中能够保存方法的变量指的就是普通的对象。Java最常用的闭包实现办法(内部类+接口)。通俗点讲:内部类的方法既能引用宿主的私有变量,又能传入主动调用者的变量(包括 指向对象(该对象可以抽象出接口:自定义回调函数)的变量),该内部类也可抽象出接口便于扩展。内部类的模拟闭包机制还实现了窥内的效果。
由于闭包上下文中有引用指向了内部类的宿主,所以宿主对象在没有其他引用的情况下也不会被销毁,只有该闭包中的回调函数执行完,才会被GC回收。
[注:在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个*变量],比如fun(x,y){},x和y是函数自己定义的,就不是*变量,如果x是使用其他函数定义的,就是*变量
总结:了解完闭包之后,我们知道在java1.8中不需要用内部类的方式实现闭包。
Lambda表达式会被编译器转换成相应函数式接口的一个实例,它表达式提供了一个上下文环境,既能引用该实例作用域的变量,又可以引用主程序所在作用域的所有变量。这种效果就是闭包,该实例中的变量就是*变量。
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗
http://blog.csdn.net/hnust_xiehonghao/article/details/46326997