2

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

如果我错了,请纠正我:

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

因此,是否有时间或地点我应该使用匿名类而不是本地类?

编辑:看起来两者之间没有真正的区别,只取决于样式以及是否要重用该类。

为了澄清我的意思是我正在谈论的一个例子:

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

4 回答 4

2

这引起了我的兴趣,我打开 JD-GUI 来查看反编译的类。编译后的两个匿名内部类其实完全没有区别:

本地类:

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

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

匿名类:

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

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

这两种方法都是实现匿名内部类的有效方法,而且它们似乎做同样的事情。

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

于 2012-09-23T00:34:38.193 回答
0
  1. 本地类对象在初始化时更快(因为该类在启动时已经在内存中)
  2. 匿名类对象的内存消耗更少(因为惰性求值)

注意:因为 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) 的调用只会引用它。这是本地类背后的概念。

于 2012-09-23T00:30:48.307 回答
0

只是关于这一点的说明:

因此,是否有时间或地点我应该使用匿名类而不是本地类?

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

addKeyListener(new KeyListener(){

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

    // further implementation here

});

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

于 2012-09-23T00:39:50.713 回答
0

我很确定没有像 object instance 这样的东西,只是 class instance 。所以是的,为本地和匿名类型创建了一个对象。但是不同之处在于你不能重用匿名类(除非通过你在方法中使用它的方式——它有效但不是真正可维护的),所以你使用它当你正在做的事情都是一次性的。例如事件监听器。

我更喜欢命名类型而不是匿名类型。

您可能会发现这很有用

编辑: 你会发现我的问题在这里很有用。

于 2012-09-23T00:21:08.803 回答