java1.8出来好久一直没怎么关注。这段时间公司的项目数据处理,需要频繁操作集合,用for遍历集合做计算,感觉很费劲,而且有大量重复代码。可读性也不高。这时候想到java1.8新特性之一:函数式编程
一、函数式接口 (functional interface)
@FunctionalInterface
interface DoSomeThing {
int getAge(int a, int b);
static void getName() {
System.out.println("函数式接口的静态方法");
}
default void getAge() {
System.out.println("函数式接口的默认方法");
}
}
如果一个方法接受一个函数式接口作为参数,那么我们可以传入以下类型作为参数:
二、闭包(closure)(回顾)
lambda表达式大量用到了闭包和函数回调,java1.8之前不支持显性闭包,要实现代码片段的传递,只能通过内部类的方式,模拟闭包。
闭包简而言之就是 含有状态的函数。
在java语言中,闭包的应用:一个代码段被用来做为方法的参数.
java中没有直接使用某个方法做为另一个方法的参数的,java使用匿名内部类来模拟这种情况。
比如一个二元函数 f _x,y,x,y是函数内部使用的变量,在只给定 一个参数 x = 7 的情况下, x 已经绑定,但是y还是自由的,这个时候 f(7, y) 就相当于含有一个私有变量(x=7)的函数了。当再给定另外一个变量 y 的值就可对函数完整的求值。所以函数中 有的参数是绑定的,有的参数自由的,这样的机制称为闭包。
闭包的价值在于可以作为函数对象或者匿名函数,持有上下文数据,作为第一级对象进行传递和保存。闭包中的部分变量没有在引用者的作用域内声明,对于引用者这些变量就是自由变量。java中能够保存方法的变量指的就是普通的对象。Java最常用的闭包实现办法(内部类+接口)。通俗点讲:内部类的方法既能引用宿主的私有变量,又能传入主动调用者的变量(包括 指向对象(该对象可以抽象出接口:自定义回调函数)的变量),该内部类也可抽象出接口便于扩展。内部类的模拟闭包机制还实现了窥内的效果。
由于闭包上下文中有引用指向了内部类的宿主,所以宿主对象在没有其他引用的情况下也不会被销毁,只有该闭包中的回调函数执行完,才会被GC回收。
[注:在A作用域中使用的变量x(A一般为主线程的方法,主动调用者),却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量],比如fun(x,y){},x和y是函数自己定义的,就不是自由变量,如果x是使用其他函数定义的,就是自由变量
总结:了解完闭包之后,我们知道在java1.8中不需要用内部类的方式实现闭包。
Lambda表达式会被编译器转换成相应函数式接口的一个实例,它表达式提供了一个上下文环境,既能引用该实例作用域的变量,又可以引用主程序所在作用域的所有变量。这种效果就是闭包,该实例中的变量就是自由变量。
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗
http://blog.csdn.net/hnust_xiehonghao/article/details/46326997
一个groovy闭包就像一个代码块或者方法指针,他是定义然后执行的一段代码,但是他有一些特性:隐含变量,支持自由变量,支持currying 。
我们先来看看一些例子:
1 |
def clos = { println "hello!" } |
2 |
3 |
println "Executing the Closure:" |
4 |
clos() //prints "hello!" |
在上面的例子中”hello!”是因为调用clos()函数才打印出来的,而不是在定义的时候打印出来的。
闭包的参数在->之前列出,比如:
1 |
def printSum = { a, b -> print a+b } |
2 |
printSum( 5 , 7 ) //prints "12" |
如果闭包的参数是少于2个的话,那么 ->是可以省略的。
A Closure without -> , i.e. {} , is a Closure with one argument that is implicitly named as ‘it’. (see below for details) In some cases, you need to construct a Closure with zero arguments, e.g. using GString for templating, defining EMC Property etc. You have to explicity define your Closure as { -> } instead of just { }
You can also use varargs as parameters, refer to the Formal Guide for details. A JavaScript-style dynamic args could be simulated, refer to the Informal Guide.
闭包能引用在参数列表中没有列出的变量,这些变量成为自由变量,他们的作用范围在他们定义的范围内:
1 |
def myConst = 5 |
2 |
def incByConst = { num -> num + myConst } |
3 |
println incByConst( 10 ) // => 15 |
另外一个例子:
1 |
def localMethod() { |
2 |
def localVariable = new java.util.Date() |
3 |
return { println localVariable } |
4 |
} |
5 |
6 |
def clos = localMethod() |
7 |
8 |
println "Executing the Closure:" |
9 |
clos() //prints the date when "localVariable" was defined |
如果你有一个闭包但是只有一个参数,那么你可以省略这个参数,比如:
1 |
def clos = { print it } |
2 |
clos( "hi there" ) //prints "hi there" |