Java匿名类与Objective-C块相比的局限性

Java匿名类与Objective-C块相比的局限性,java,objective-c,closures,block,Java,Objective C,Closures,Block,在Objective-C中发现了块之后,我才开始对一阶函数和闭包进行研究。Java是我听说过闭包(或缺少闭包)以及匿名类如何在某种程度上弥补闭包的另一种语言 我可以肯定地看到Objective-C中闭包作为块的优点,但是匿名Java类的局限性是什么?它们在多大程度上“某种程度上”弥补了真正闭包的不足?Java匿名类确实非常冗长。除了定义它们所需的大量样板文件外,Java的一些设计决策意味着许多常见任务比其他语言要详细得多。例如,在Java中,将可变的upvalues导入闭包是一件痛苦的事情 基本

在Objective-C中发现了块之后,我才开始对一阶函数和闭包进行研究。Java是我听说过闭包(或缺少闭包)以及匿名类如何在某种程度上弥补闭包的另一种语言


我可以肯定地看到Objective-C中闭包作为块的优点,但是匿名Java类的局限性是什么?它们在多大程度上“某种程度上”弥补了真正闭包的不足?

Java匿名类确实非常冗长。除了定义它们所需的大量样板文件外,Java的一些设计决策意味着许多常见任务比其他语言要详细得多。例如,在Java中,将可变的upvalues导入闭包是一件痛苦的事情

基本上,Java不支持upvalues;相反,通过将它们(按值)通过不可见的参数传递给类的构造函数来模拟它们。因为它们是按值传递的,所以在类内修改它们不会影响构造类的方法中的副本,因此编译器会让您声明它们为最终值,以避免混淆自己。e、 g:

Runnable function()
{
   final int i = 4;
   return new Runnable()
   {
       public void run()
       {
            System.out.println("i="+i);
            // can't modify i here
       }
   }
}
在您确实需要修改变量的情况下,例如在几乎所有闭包有用的情况下,您必须作弊:

Runnable function()
{
   final int[] i = new int[1];
   i[0] = 4;
   return new Runnable()
   {
       public void run()
       {
            System.out.println("i="+i[0]);
            i[0] = i[0] + 1;
       }
   }
}
在这里,
i
本身仍然是不可变的,但是因为它指向一个可变的对象,所以我可以更改对象的内容。(当然,在现实生活中,我会使用类而不是数组,因为使用数组真的很难看。这使得它更加冗长。)


我推测下一个Java版本将有语法糖来简化所有这些,但现在以闭包为中心的编程在Java中相当麻烦。我发现,改变逻辑不使用闭包通常更容易,只是为了让我能够将使用的代码量保持在足够小的程度,以便于理解。

我不太了解objective-C版本的闭包,但我从Smalltalk和Lua中了解它们

闭包本质上是一个函数,它可以访问其他函数/块的局部变量(通常闭包是语法嵌套的)。这样,局部变量可以比它在其中定义的块活得更长。当同一变量上有多个闭包时,它们可以使用此变量进行通信

Java的本地类(匿名类是其中的一个特例)支持有限的版本:它们允许访问
final
变量,即不能更改其值的变量。这是通过将此变量的值复制到其构造上的本地类对象来实现的。您可以通过在此变量中使用可变对象(在最简单的情况下是一个元素数组)来模拟实际闭包


此外,Java语法非常难看,但它与语言的其余部分很好地配合,并允许静态类型安全(与前面讨论的一些较短的语法变体相反)。

除了语法的灵活性之外,你是说?是的。这一点很明显:这是一个关键点——虽然Java anon内部类很难看,但它们也和“漂亮的闭包”一样强大,并保持绑定(最终变量的绑定,但它们可以包含可变对象)。Scala(支持一级函数)只是隐藏了所有这些繁琐的丑陋,但在其背后却以类似的方式运行。啊,我想在这里提到可变对象。这个功能从Java 7中删除,该功能将于本月或下个月发布,并推到Java 8中,该功能将于2012年12月发布。或者,如果不需要在闭包和定义闭包的作用域之间共享状态,为什么不将其分配给类中的变量呢最终积分i=4;返回new Runnable(){int m=i;public void run(){System.out.println(“m=“+m);m++;}}}}`这是一个我没有想到的巧妙技巧。当然,只有当您不想将状态从内部类导出到外部时,它才有用,但是仍然很方便,我会记住它。谢谢我想说的是,因为我们正在与Objective-C块进行比较,所以您提到的许多东西同样适用于Objective-C块:默认情况下,块按值捕获变量,捕获变量是闭包内的
const
;这类似于Java匿名函数通过值捕获并强制变量为
final
。为了能够在块中修改捕获的变量,它需要在其原始范围内显式声明为_块;这类似于在Java中创建一个1元素数组来共享状态,只是没有显式解包。