一、与闭包有关的JAVA语法
JAVA中的闭包,与内部类、匿名内部类和其语法糖 lambda 密切相关。
JAVA内部类可以直接访问外部类的私有变量,反之亦然。
定义在函数体内的内部类,也可以访问函数体内的变量,变量名使用final修饰(JDK8开始可以直接访问,不需要final,但建议读者坚持使用final,增强代码可读性)。
二、什么是闭包?
引用了自由变量的函数就是闭包,通过嵌套函数产生闭包,闭包是一个嵌套函数。
三、闭包的典型应用
3.1 支持柯里化
柯里化的实质是内部实现类的嵌套。
public class Currying {//柯里化的目标public static int add(int x, int y,int z) {return x + y + z;}public interface UnaryAdd { //一元接口int add(int z);}public interface BinaryAdd {UnaryAdd add(int y);}public interface TernaryAdd {BinaryAdd add(int x);}public static void main(String[] a) {System.out.println(add(2, 3, 4));TernaryAdd v = x-> y -> z -> x + 2*y - z;//System.out.println(v.add(2).add(3).add(4));v = new TernaryAdd(){@Override public BinaryAdd add(int x){return new BinaryAdd(){//闭包@Override public UnaryAdd add(int y){return new UnaryAdd(){//闭包@Override public int add(int z){return x + y + z;}};}};}};System.out.println(v.add(2).add(3).add(4));}}
3.2 支持函数的组合
输出x-y之间符合一定条件的数字。
我们把条件抽象为 Condition函数式接口。
@FunctionalInterfacepublic interface Condition {public boolean test(int n);}public class Filter {public static void filter(int x, int y, Condition c) {for (int i = x; i <= y; i++) {if (c.test(i)) {System.out.print(" " + i);}}}}public class Client {public static void main(String[] args) {Filter.filter(1, 100, n -> n % 3 == 0);}}
上面是模板方法的应用。
如果filter需要进行多种条件的测试,我们该怎么做?
更改filter方法形参,接受Condition…可变参数?这改变了模板方法,filter可能已经被使用多次,改变它不是一个好主意。
重新实现一个Condition?可以,但是这给程序员增加了负担,也使得代码变得臃肿。
更好的方法是能够将多个Condition组合起来。
本质就是组合的对象。
@FunctionalInterfacepublic interface Condition {public boolean test(int n);default Condition and(Condition other){return n-> this.test(n) && other.test(n);// return new Condition() {// @Override// public boolean test(int n) {// return Condition.this.test(n) && other.test(n);// }// };}default Condition or(Condition other){return n-> this.test(n) || other.test(n);}default Condition not(){return n-> !this.test(n);}}public class Client {public static void main(String[] args) {Condition c = n -> {while (n > 0) {if (n % 5 == 0) return true;n = n / 10;}return false;};Filter.filter(1, 100, c.and(n -> n % 3 == 0));}}
