闭包
定义
示例
注意
这个外部变量 x 必须是effective final
- 你可以生命他是final,你不声明也会默认他是
final
的,并且具有final的特性,不可变
- 一旦x可变,他就不是final,就无法形成闭包,也
无法与函数对象一起使用
这个地方存在一个取巧的行为
- 你可以
选择一个引用对象
,逻辑中使用的是这个对象的某个属性
,改变属性达到改变逻辑的效果,但是这个引用没有发生变化,这个对象还是这个对象,只不过属性值发生了变化。
闭包使用示例
- for循环的i是变化的,无法直接作为闭包变量,可以每次生命一个新的k值来接收i
for (int i = 0; i < 10; i++) {
// 每次循环都创建一个新的final变量k
int k = i;
Thread thread = new Thread(() -> {
System.out.println("线程" + k + "执行");// 这里会报错 直接使用i会报错 因为i是final的
});
thread.start();
}
柯里化
定义
注意
柯里化是建立在闭包的基础上的
实例
使用lambda实现函数式接口
常规写法:多个参数
int a = 10;
int b = 20;
// 常规写法
MyInterface myInterface = (int x,int y) -> {
System.out.println(x + y);
};
myInterface.method(a,b);
@FunctionalInterface
public interface MyInterface {
void method(int a,int b);
}
- 有点类似于
递归调用
每一次都返回的是一个函数,没有切实的方法体,只为了传递参数
只有第一层有所有的参数,有实际的方法体
// 柯里化写法 一个函数返回一个函数 每次调用返回的函数都是一个新的函数 每个函数都有一个参数
// 这个地方其实就是隐式地使用了柯里化
MyInterface3 myInterface3 = x -> y -> {
System.out.println(x + y);
};
MyInterface2 myInterface2 = myInterface3.method(a);
myInterface2.method(b);
@FunctionalInterface
public interface MyInterface2 {
void method(int a);
}
@FunctionalInterface
public interface MyInterface3 {
// 返回一个函数
MyInterface2 method(int b);
}
柯里化的作用
练习
public class Main3 {
public static void main(String[] args) {
List<Integer> list = step3(step2(step1()));
System.out.println(list);
}
/*
* 函数式接口1:F1 收集第一个list 返回一个函数式接口2
* 函数式接口2:F2 收集第二个list 返回一个函数式接口3
* 函数式接口3:F3 收集第三个list 执行具体逻辑
* */
@FunctionalInterface
interface F1 {
// 收集第一个list 返回一个函数式接口2
F2 method(List<Integer> list);
}
@FunctionalInterface
interface F2 {
// 收集第二个list 返回一个函数式接口3
F3 method(List<Integer> list2);
}
@FunctionalInterface
interface F3 {
// 收集第三个list 执行具体逻辑
List<Integer> method(List<Integer> list3);
}
// 第一步
public static F2 step1 (){
// 第一个list
List<Integer> list1 = Arrays.asList(1, 2, 3);
// 因为第一在最外层 所以是一个三层嵌套的函数
// 方法体已经定义完毕 但是这个方法体并没有执行 这个方法体是在step3中执行的
F1 step1 = a -> b -> c -> {
List<Integer> newList = new ArrayList<>();
newList.addAll(a);
newList.addAll(b);
newList.addAll(c);
return newList;
};
// 执行step1的方法体 收集第一个list 返回一个函数式接口2
return step1.method(list1);
};
public static F3 step2 (F2 f2){
List<Integer> list2 = Arrays.asList(4, 5, 6);
// 执行step2的方法体 收集第二个list 返回一个函数式接口3
return f2.method(list2);
};
public static List<Integer> step3 (F3 f3){
List<Integer> list3 = Arrays.asList(7, 8, 9);
// 执行step3的方法体 收集第三个list 执行具体逻辑
return f3.method(list3);
};
}