一、与闭包有关的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函数式接口。
@FunctionalInterface
public 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组合起来。
本质就是组合的对象。
@FunctionalInterface
public 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));
}
}