Java"闭包"本地和匿名类之间的比较

时间:2012-09-23 00:09:57

标签: java closures

我已经对使用匿名类和本地类实现闭包的区别进行了一些搜索。我试图找出两者之间的所有差异所以我知道在哪种情况下哪种方法更好。

如果我错了,请纠正我:

  • 每次创建新实例时,匿名类都会创建一个类实例和对象实例。
  • 每次创建新实例时,本地类只创建一个对象实例。

因此,有没有时间或地点我应该在本地课堂上使用匿名课程?

编辑:看来两者之间没有真正的区别,只是取决于风格,如果你想重用这个类。

澄清我在这里的意思是我所谈论的一个例子:

public class ClosureExample {
interface Function {
    void func(int value);
}

public static void main(final String[] args) {
    final Function local1 = localClassClosure("Local1");
    final Function local2 = localClassClosure("Local2");

    final Function anonymous1 = anonymousClassClosure("Annonymous1");
    final Function anonymous2 = anonymousClassClosure("Annonymous2");

    for (int i = 0; i < 3; i++) {
        local1.func(i);
        local2.func(i);
        anonymous1.func(i);
        anonymous2.func(i);
    }
}

private static Function localClassClosure(final String text) {
    // Local class name is irrelevant in this example
    class _ implements Function {
        @Override public void func(final int value) {
            System.out.println(text + ":" + value);
        }
    }
    return new _();
}

private static Function anonymousClassClosure(final String text) {
    return new Function() {
        @Override public void func(final int value) {
            System.out.println(text + ":" + value);
        }
    };
}
}

希望有人可以详细解释这种微妙的差异,以及在哪种情况下应使用哪种方法。

4 个答案:

答案 0 :(得分:2)

这引起了我的兴趣,我打破了JD-GUI来查看反编译的类。在编译之后,两个匿名内部类之间实际上没有任何区别:

localClass:

class ClosureExample$1t implements ClosureExample.Function{
  ClosureExample$1t(String paramString){
  }

  public void func(int value){
    System.out.println(this.val$text + ":" + value);
  }
}

anonymousClass:

class ClosureExample$1 implements ClosureExample.Function{
  ClosureExample$1(String paramString){
  }

  public void func(int value){
    System.out.println(this.val$text + ":" + value);
  }
}

这两种方法都是实现匿名内部类的有效方法,它们似乎完全相同。

编辑:我将_类重命名为t

答案 1 :(得分:0)

我很确定没有像对象实例,只是类实例。 所以是的,为本地和匿名类型创建了一个对象。  然而,区别在于你不能重用匿名类(除非你在你的方法中使用它的方式 - 它可以工作但不能真正维护),所以当你正在做的任何事情都是一次性的时候你使用它。例如,使用事件监听器。

我更喜欢命名类型为匿名类型。

You might find this useful

修改 您会发现我的question非常有用。

答案 2 :(得分:0)

  1. 本地类对象在初始化时更快(因为该类在启动时已经在内存中)
  2. 匿名类对象占用内存较少(因为评估为懒惰)
  3. 注意:因为java不是真正的函数式语言。匿名类将被预先评估,甚至存储在类文件中。所以真的没什么区别。

    在函数式语言中,如scheme:

    (define inc (lambda (a) (lambda () (+ 1 a))))
    (display ((inc 5))) 
    

    函数(lambda()(+ 1 a))实际上会在每次匿名调用中重新创建,如((inc 5))。这是背后匿名类的概念。

    相反:

    (define inc (lambda (a) (+ 1 a)))
    (display (inc 5)) 
    

    其中(lambda(a)(+ 1 a))将在编译时存储在内存中,对(inc 5)的调用只会引用它。这是本地类背后的概念。

答案 3 :(得分:0)

关于这一点的说明:

  

因此,是否有时间或地点我应该在本地课堂上使用匿名课程?

如果您需要快速设置事件监听器[例如在组件内部KeyListener],您可以这样做:

addKeyListener(new KeyListener(){

    public void keyPressed(KeyEvent ke){ ... }

    // further implementation here

});

虽然它根本不可重复使用。