Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 编译器是否优化不添加/重写方法的匿名类?_Java_Android_Coding Style - Fatal编程技术网

Java 编译器是否优化不添加/重写方法的匿名类?

Java 编译器是否优化不添加/重写方法的匿名类?,java,android,coding-style,Java,Android,Coding Style,我想知道编译器(ECJ、javac或您最喜欢的编译器)是否优化了匿名类,这些匿名类不会添加或重写基类的方法 例如,对于如下所示的代码: 片段A: 我总是更喜欢语法: 片段B: 然而,我明白,与vb.net中的WITH关键字不同,这不仅仅是语法上的糖分。我们告诉编译器要做的是创建一个匿名的Human子类,其构造函数由大括号中的代码组成(这也是为什么我们不能对最终类使用这种语法) 现在的问题是,我一直在使用这种语法(比如在UI监听器中重写onclick等),这就像我的一种编码风格/习惯 因此,问题是

我想知道编译器(ECJ、javac或您最喜欢的编译器)是否优化了匿名类,这些匿名类不会添加或重写基类的方法

例如,对于如下所示的代码:

片段A:

我总是更喜欢语法:

片段B:

然而,我明白,与vb.net中的
WITH
关键字不同,这不仅仅是语法上的糖分。我们告诉编译器要做的是创建一个匿名的Human子类,其构造函数由大括号中的代码组成(这也是为什么我们不能对最终类使用这种语法)

现在的问题是,我一直在使用这种语法(比如在UI监听器中重写onclick等),这就像我的一种编码风格/习惯

因此,问题是:

  • 编译器是否优化了这种语法?(即,它意识到不需要生成匿名类,代码段B的性能将与代码段A相同)

  • 如果(1)的答案是“否”,我想知道(由于这种编码风格,匿名类的数量超过预期)是否会产生显著影响,因此强烈建议在未来的项目中(为普通移动设备编码应用程序),我们应该始终坚持片段a中的风格


  • 编译器将创建一个单独的二进制类

    例如,如果你有

    class Foo{
    
    }
    
    class Bar{
      Foo otherFoo = new Foo(){
    
      }
    }
    
    在bin/target目录中,您将有三个类

    • 酒吧
    • 一美元一班
    • Foo.class
    这里的匿名子类是Bar$1。class

    是的,它将(始终)生成一个匿名类(称为Human$1)。通过检查输出的类文件可以看到这一点。您应该有一个Human.class和Human$1.class作为输出

    至于性能影响,将有两个类(更大,VM的工作更多),从一个到另一个的引用(因为匿名内部类将有一个到外部类的链接)。我想这可能对性能有影响,但影响很小。你得测试一下


    然而,这样做并不是java特有的习惯用法。惯用的方法是使用另一个构造函数。

    不幸的是,我不知道编译器将如何处理它。但是你可以自己编写一个循环,多次同时执行这两种方法,并进行测量,以了解这两种方法的性能影响。@Tim是的,但唯一的问题是,像这样做测试根本不准确。例如,在真实的应用程序中,这种代码不会在代码的某一部分中循环运行,而是在整个代码中从应用程序生命周期的开始到应用程序生命周期的结束都以位和块的形式运行(这类似于我们使用
    if
    else
    语句,它们是整个代码的一部分,而不是像循环中那样使用say)请注意:您没有定义构造函数,而是定义了一个初始值设定项块。这些块是在构造函数之前执行的!因此,您不能依赖其他字段是否已经使用这种方法创建了。我一直在努力解决这一问题,并且经常使用类似的类,但最近我选择了返回
    this
    ins的setter代替了
    void
    ,这样你就可以把它们或一个构建器模式链接起来;
    Eat(new Human("John", 30){
        {
            setX(12.5);
            setY(15.3);
            //..
        }
    });
    
    class Foo{
    
    }
    
    class Bar{
      Foo otherFoo = new Foo(){
    
      }
    }