我首先问过这个问题,关于在Java中使用final
和匿名内部类:
Why do we use final keyword with anonymous inner classes?
我实际上正在阅读马丁奥德斯基的Scala书。似乎Scala简化了许多Java代码,但对于Scala闭包,我注意到了一个显着的差异。
在Java中,我们使用匿名内部类“模拟”闭包,捕获最终变量(将被复制到堆上而不是堆栈中),在Scala中我们可以创建一个可以捕获val,也是一个var,因此在闭包调用中更新它!
所以我们可以使用没有final
关键字的Java匿名内部类!
我还没读完这本书,但是现在我没有找到关于这种语言设计选择的足够信息。
有人可以告诉我为什么马丁奥德斯基真的好好照顾功能的副作用,选择闭包来捕捉val
和var
,而不仅仅是val
?
Java和Scala实现的优点和缺点是什么?
由于
相关问题: With Scala closures, when do captured variables start to live on the JVM heap?
答案 0 :(得分:8)
可以看到一个对象可以共享对同一环境的访问,并且该环境通常是可变的。那么为什么使匿名函数生成的闭包不那么强大呢?
此外,具有可变变量和匿名函数的其他语言也以相同的方式工作。租赁惊讶原则。 Java实际上是WEIRD,不允许内部类捕获可变变量。
有时它们只是非常有用。例如,自修改thunk以创建自己的惰性或未来处理变体。
缺点?它们具有共享可变状态的所有缺点。
答案 1 :(得分:1)
以下是一些优点和缺点。
语言设计中有一个原则是程序员应该明白某些东西的成本。 (我首先在霍尔特的图灵语言的设计和定义中看到了这一点,但我忘记了他给出的名字。)两件看起来相同的东西应该是相同的。两个当地的vars应该有类似的成本。这有利于Java。 Java中的两个本地变量实现相同,因此无论是否在内部类中提及其中一个变量,它们的成本相同。 Java最受青睐的另一点是,在大多数情况下,捕获的变量确实是最终的,因此程序员无法捕获非最终本地变量的成本很低。最后的坚持也简化了编译器,因为它意味着所有局部变量都是堆栈变量。
语言设计的另一个原则是正交。如果可以捕获val,为什么不能使用var。只要有明智的解释,为什么要加以限制。当语言不够正确时,它们似乎有悖常理。另一方面,具有太多正交性的语言可能具有复杂的(因此有缺陷和/或迟到和/或很少)实现。例如,Algol 68在黑桃中具有正交性,但实施它并不容易,这意味着很少实现并且很少采用。 Pascal(大约在同一时间设计)具有各种不优雅的限制,使编写编译器更容易。结果是大量的实施和大量的采用。