编译器是否优化了不添加/覆盖方法的匿名类?

时间:2011-11-04 15:24:08

标签: java android coding-style

我想知道编译器(ECJ,javac,或者你可以命名你喜欢的编译器)是否优化了匿名类,这些类不会添加或覆盖它的基类方法。

例如,对于看起来像这样的代码:

Snippet A:

Human h = new Human("John", 30);
h.setX(12.5);
h.setY(15.3);
//..
Eat(h);

我总是喜欢这种语法:

Snippet B:

Eat(new Human("John", 30){
    {
        setX(12.5);
        setY(15.3);
        //..
    }
});

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

现在的问题是我一直使用这种语法 - 糖 (例如在UI听众中覆盖onclick等),这就像我的编码风格/习惯之一。

因此问题:

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

  2. 如果(1)的答案是“否”,我想知道(由于这种编码风格,超出预期的丰富的匿名类)是一个明显的影响因此强烈建议对于未来的项目(平均移动设备的编码应用程序),我们应始终遵循 Snippet A 中的样式?

2 个答案:

答案 0 :(得分:1)

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

例如,如果你有

class Foo{

}

class Bar{
  Foo otherFoo = new Foo(){

  }
}

在bin / target目录中,您将有三个类

  • Bar.class
  • 酒吧$ 1.class
  • 让Foo.class

这里的匿名子类是Bar$1.class

答案 1 :(得分:1)

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

至于性能影响,将有两个类(更大,更多的VM工作),从一个到另一个的引用(因为匿名内部类将具有到外部类的链接)。我想这可能对性能有影响,但只是次要的。你必须测试它。

但是,这样做并不是特别惯用的java。惯用的方法是拥有另一个构造函数。