什么';Java中的匿名类和闭包之间的区别是什么?

什么';Java中的匿名类和闭包之间的区别是什么?,java,closures,terminology,anonymous-class,Java,Closures,Terminology,Anonymous Class,看起来匿名类提供了闭包的基本功能,是真的吗?IMHO,它们也有类似的用途,但是闭包的目的是更简洁,并可能提供更多的功能 假设要使用匿名类使用局部变量 final int[] i = { 0 }; final double[] d = { 0.0 }; Runnable run = new Runnable() { public void run() { d[0] = i[0] * 1.5; } }; executor.submit(run); 闭包允许您编写

看起来匿名类提供了闭包的基本功能,是真的吗?

IMHO,它们也有类似的用途,但是闭包的目的是更简洁,并可能提供更多的功能

假设要使用匿名类使用局部变量

final int[] i = { 0 };
final double[] d = { 0.0 };

Runnable run = new Runnable() { 
    public void run() {
        d[0] = i[0] * 1.5;
    }
};
executor.submit(run);
闭包允许您编写所需内容,从而避免了大多数锅炉板编码的需要

int i = 0;
double d = 0.0;

Runnable run = { => d = i * 1.5; };
executor.submit(run);
甚至

executor.submit({ => d = i * 1.5; });
或者如果闭包支持代码块

executor.submit() {
    d = i * 1.5; 
}

只要它们都影响“私人”范围界定,在非常有限的意义上,是的。然而,有如此多的差异,答案可能是否定的

由于Java缺乏将代码块作为真正的R值处理的能力,内部类无法像通常在continuations中那样传递代码块。因此,作为延续技术的闭包是完全缺失的

虽然要进行垃圾收集的类的生存期是由持有内部类的人延长的(类似于闭包在恢复到闭包时保持变量活动),但Java通过绑定进行重命名的能力是有限的,以符合现有的Java语法

为了允许线程使用Java的线程争用模型正确地不践踏彼此的数据,内部类进一步受到限制,可以访问保证不会打乱的数据,也就是最终局部变量


这完全忽略了感觉稍有不同的其他内部类(也称为静态内部类)。换言之,它涉及到关闭的一些项目可以处理,但低于大多数人认为需要被称为闭包的最低要求。

几乎没有差别。事实上,关于闭包和对象有一句老话。闭包是穷人的对象,对象是穷人的闭包。就他们的能力而言,两者都同样强大。我们只是在争论表达能力

在Java中,我们使用匿名对象对闭包进行建模。事实上,这里有一点历史是,最初Java能够在不使用final的情况下修改外部范围。这对于在本地方法范围内分配的对象很有效,但对于原语,这引起了很多争议。原语是在堆栈上分配的,因此为了使它们能够通过外部方法的执行,Java必须在堆上分配内存并将这些成员移动到堆中。当时,人们对垃圾收集非常陌生,他们不信任垃圾收集,因此声称Java不应该在没有程序员明确指示的情况下分配内存。为了达成妥协,Java决定使用final关键字

现在有趣的是,Java可以删除这个限制,并使用最后一个关键字optional,因为现在每个人都对垃圾收集器比较熟悉,而且从语言的角度来看,它可以完全兼容。虽然解决这个问题的方法很简单,但可以在匿名对象上定义实例变量,并且可以根据需要修改它们。事实上,通过编译器向匿名类添加公共实例变量,并重写源代码以使用这些变量而不是堆栈变量,这可能是实现对本地范围的闭包式引用的一种简单方法

public Object someFunction() {
   int someValue = 0;

   SomeAnonymousClass implementation = new SomeAnonymousClass() {
       public boolean callback() {
           someValue++;
       }
   }
   implementation.callback();
   return someValue;
}
将改写为:

 public Object someFunction() {
   SomeAnonymousClass implementation = new SomeAnonymousClass() {
       public int someValue = 0;

       public boolean callback() {
           someValue++;
       }
   }
   implementation.callback();

   // all references to someValue could be rewritten to 
   // use this instance variable instead.
   return implementation.someValue;
}
我认为人们抱怨匿名内部类的原因更多地与静态类型和动态类型有关。在Java中,我们必须为匿名类的实现者和接受匿名类的代码定义一个商定的接口。我们必须这样做,以便在编译时对所有内容进行类型检查。如果我们有第一类函数,那么Java将需要定义一种语法,将方法的参数和返回类型声明为数据类型,以保持静态类型语言的类型安全性。这几乎和定义接口一样复杂。(一个接口可以定义多个方法,声明第一类方法的语法只能用于一个方法)。您可以将其视为一种简短的接口语法。在这种情况下,编译器可以在编译时将简短形式的符号转换为接口


在不放弃Java语言或进行重大手术的情况下,可以对Java做很多事情来改善匿名课堂体验。

为什么要否决投票?他正试图就自己对闭包的看法获得反馈,如果这是错误的,请解释原因。。。不是否决票?我建议你在博客上读一读“Java中的块”,它会引导你了解闭包和内部类。实际上+1个好问题。。匿名类经常与闭包相比较(通常只有忽略差异的Java编码人员才会这样做),这是一个好问题。顺便说一下:Wikipedia的文章将Java的内部类列为(模拟的?)闭包:。这有点像说“C宏提供了Lisp宏的基本特性”;稍微正确,但大部分是错误的同意。相同,但大部分不同。这个答案应该更新(即Java8)。你应该多解释一下闭包的定义。例如,根据一些人对闭包的定义,Haskell没有有效的闭包(因为您不能修改绑定的变量…就像Java final一样)。要绑定的变量的
final
在这一点上主要是为了向后兼容。有趣的是,我没有看到另一个答案有不同的观点,但它淡化了作用域,认为它不相关,即使它的示例强调了作用域的差异(这很奇怪,但这是一个奇怪的世界)。从功能上讲,这两者是相似的,除了我的答案试图比较两个不同的世界(纯功能和纯OO),另一个主要展示OO如何建模功能结构(通过使用对象建模)。“对象是穷人的闭包”的说法是不正确的(但