回复内容:题主要变通…
java 8语言上的lambda表达式只实现了capture-by-value,也就是说它捕获的局部变量都会拷贝一份到lambda表达式的实体里,然后在lambda表达式里要变也只能变自己的那份拷贝而无法影响外部原本的变量;但是java语言的设计者又要挂牌坊不明说自己是capture-by-value,为了以后语言能进一步扩展成支持capture-by-reference留下后路,所以现在干脆不允许向捕获的变量赋值,而且可以捕获的也只有“效果上不可变”(effectively final)的参数/局部变量。
关于java闭包的讨论可以参考我之前的另一个回答:jvm的规范中允许编程语言语义中创建闭包(closure)吗? - rednaxelafx 的回答
但是java只是不允许改变被lambda表达式捕获的变量,并没有限制这些变量所指向的对象的状态能不能变。要从lambda表达式向外传值的常见workaround之一就是用长度为1的数组:string[] a = new string[1];... ( () -> a[0] = a );return a[0];
/* 你可以用atomicreference将你所需要的值包装起来 */private static int sum(int low, int high) { atomicreferenceinteger> sum = new atomicreference(0); intstream.rangeclosed(low, high).foreach(i -> sum.set(sum.get() + i)); return sum.get();}/* 对于基本类型有专用的包装类更方便使用(且是原子化操作) */private static int sum2(int low, int high) { atomicinteger sum = new atomicinteger(0); intstream.rangeclosed(low, high).foreach(sum::addandget); return sum.get();}/* 其实很多时候,我们并不需要改变外部状态不是吗? */private static int sum3(int low, int high) { return intstream.rangeclosed(low, high).sum();}
c++:可以
c#:可以
f#:可以
vb:可以
补充 @vczh
javascript:也可以
欢迎加入java黑的大家庭。void someobject somemethod(supplieroptionalobject>> foo) { return foo.get().map(a -> ((object a) -> ...)).orelseget(() -> ...);}
java的函数无法进行引用传递,闭包的捕获也一样。so sad。什么叫不能向外传递值?
改一个field叫不叫传递值? 调用另外的方法叫不叫传递值?java:如果我有指针或者引用。
指针:怪我了?
引用:……你的需求就是多种返回值,那么为什么不考虑使用异常?比修改外部变量来的高明。在开发过程中,其实异常是可以作为逻辑的一部分的。
