如果经常使用lambda表达式,一定会对这个约束感觉非常麻烦,非常费解为何Java有此限制;
网络上大多的文章往往都是分析Java如何去实现匿名内部类,比如是对当前局部变量引用的copy; 但是似乎都没清晰说明必须申明为final的理由;
下面是一些 信息和猜测
- 这个限制其实是只针对于局部变量(local variable) 而对成员变量(field)并无final限制;这个也很好理解,因为ACI 并没有直接引用field, 而是引用当前的外部对象本身this; 本质而言, 只是限定它直接引用的变量引用不可变;
- 其实想回避上面该问题已经有一种简单的代码范式,叫做手动boxing(JDK源码里自己都在用);如下面代码,简单的用另一个东西封装一下需要被修改的内容,就可绕过这个限制(其实也理解为field是被this封装过,所以可以绕过限制);
Integer[] ia = new Integer[0];
ia[0] = 31;
ia[0] = 32;
Integer i = 0;
i = 31;
i = 32;
Supplier<Integer> s = ()->{
return ia[0];
//cannot compile
return i;
};
- 关于引入这个控制的原因。首先技术上我觉得不存在问题,与当前JVM的设计不存在冲突问题,而且在其他类Java的语言里也早已经做到;我见到有许多人回答,可能导致的Sync Problem, 这个也算是个合理的理由。lamdba 表达式时,它的目的不仅仅为了让代码书写更加简练,同样重要的是支持并行计算的特性(也就是多线程)。可能JCP设计时,就默认每个lamdba就必须考虑多线程并发问题;这个约束在我看来并不能解决线程安全的问题,但它可以提醒开发者注意可能的线程安全问题(就像Optional可以强制开发者考虑null exception问题);