Java 爪哇语;“关闭”;本地类与匿名类的比较

Java 爪哇语;“关闭”;本地类与匿名类的比较,java,closures,Java,Closures,我已经研究了使用匿名类和本地类实现闭包的区别。我试图找出两者之间的所有差异,以便我知道哪种方法在哪种情况下更好 如果我错了,请纠正我: 匿名类在每次创建新实例时都会创建一个类实例和对象实例 每次创建新实例时,本地类仅创建一个对象实例 因此,是否有一个时间或地点我应该使用匿名类而不是本地类 编辑:这两者似乎没有真正的区别,只是取决于样式和是否要重用该类 为了澄清我的意思,这里有一个我所说的例子: public class ClosureExample { interface Function

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

如果我错了,请纠正我:

  • 匿名类在每次创建新实例时都会创建一个类实例和对象实例
  • 每次创建新实例时,本地类仅创建一个对象实例
因此,是否有一个时间或地点我应该使用匿名类而不是本地类

编辑:这两者似乎没有真正的区别,只是取决于样式和是否要重用该类

为了澄清我的意思,这里有一个我所说的例子:

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);
        }
    };
}
}
公共类closure示例{
接口函数{
void func(int值);
}
公共静态void main(最终字符串[]args){
最终函数local1=localClassClosure(“local1”);
最终函数local2=localClassClosure(“local2”);
最终函数anonymous1=anonymousClassClosure(“Annonymous1”);
最终函数anonymous2=anonymousClassClosure(“Annonymous2”);
对于(int i=0;i<3;i++){
local1.func(i);
local2.func(i);
匿名1.func(i);
匿名2.func(i);
}
}
私有静态函数localClassClosure(最终字符串文本){
//在本例中,本地类名是不相关的
类uu实现函数{
@重写公共void func(最终整数值){
System.out.println(text+“:”+值);
}
}
返回新的;
}
私有静态函数AnonymousClassClose(最终字符串文本){
返回新函数(){
@重写公共void func(最终整数值){
System.out.println(text+“:”+值);
}
};
}
}

希望有人能详细解释这种细微的差别,以及在什么情况下应该使用哪种方法。

我很确定没有什么东西像对象实例,只有类实例。 因此,是的,为本地和匿名类型创建了一个对象。。 然而,不同之处在于,您不能重用匿名类(除非通过在方法中使用匿名类的方式——这种方式可以工作,但实际上不可维护),因此,当您所做的任何事情都是一次性的时,您可以使用匿名类。例如,使用事件侦听器

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

编辑: 你会发现我在这里很有用

  • 本地类对象在初始化时速度更快(因为类在启动时已经在内存中)
  • 匿名类对象占用更少的内存(由于延迟计算)
  • 注意:因为java不是真正的函数式语言。匿名类将被预先评估,甚至存储在类文件中。所以真的不会有太大的区别

    在函数式语言中,如scheme:

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

    与之相反:

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

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

    这激起了我的兴趣,我打开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);
      }
    }
    
    这两种方法都是实现匿名内部类的有效方法,它们似乎做了完全相同的事情


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

    只是关于这一点的注释:

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

    如果需要在组件内快速设置事件侦听器[例如
    keystener
    ],可以执行以下操作:

    addKeyListener(new KeyListener(){
    
        public void keyPressed(KeyEvent ke){ ... }
    
        // further implementation here
    
    });
    

    尽管它根本不可重用。

    为什么下划线是类名?你说的类实例和对象实例是什么意思?我指的是类装入器装入JVM的类。请注意,Java 8之前的“闭包”在这个问题中讨论的不是通常公认意义上的真正闭包。不同之处在于,封闭范围内的变量都必须是
    final
    。这允许通过将这些变量的卷影副本作为隐藏变量添加到内部/匿名类来模拟闭包行为。我已经意识到我的误解在哪里,没有实际的区别,我在某个地方读到,每次创建匿名类实例时都会创建一个新类。事实并非如此。该类只创建一次。编译器正在生成一个类,您不知道该类的名称。它可能类似于“RandomClassABlah”,直到我打印出正在创建的类名,我才意识到:ClosureExample$1_uuSureExample$1_uSureExample$1 ClosureExample$1我一直希望第二个匿名类是ClosureExample$2@Jyro117你让我想起了我的问题。请参阅我的更新。因此,在初始化之后,这两种方法之间没有任何区别?几乎。。因为据我记忆所及,java实际上在运行时创建类文件,即使是匿名类。Java并不是真正的函数式语言。在函数式语言中,这两种情况之间的区别是一个基本概念。啊,没有想到在反编译后查看类。是的,很有趣,其实没有区别!