Java匿名类效率的含义

Phi*_*hil 27 java performance anonymous-class execution-time

这两种做事方式之间的效率(例如执行时间,代码大小等)是否有任何差异?

下面是创建对象并且什么也不做的人为设想的示例,但我的实际场景可能是创建新的线程,监听器等.假设以下代码片段在循环中发生,以便它可能有所作为.

使用匿名对象:

void doSomething() {
    for (/* Assume some loop */) {
        final Object obj1, obj2; // some free variables

        IWorker anonymousWorker = new IWorker() {
            doWork() {
                // do things that refer to obj1 and obj2
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

首先定义一个类:

void doSomething() {
    for (/* Assume some loop */) {
        Object obj1, obj2;
        IWorker worker = new Worker(obj1, obj2);
    }
}

static class Worker implements IWorker {
    private Object obj1, obj2;
    public CustomObject(Object obj1, Object obj2) {/* blah blah */}

    @Override
    public void doWork() {}
};
Run Code Online (Sandbox Code Playgroud)

Bri*_*new 40

唯一匿名类和顶层类之间实际差别是匿名类将保持到外部类的隐式引用.

这不会在性能方面表现出来,但如果您将这些类序列化,则会对您产生影响.

  • 如果对外部类的引用没有意义,它将影响性能 - 特别是当垃圾车滚动时.您将立即收集更多垃圾,而不是让外部类根据需要超出范围.不是一个巨大的差异,但它不容忽视. (10认同)
  • @ Cu7l4ss - 内部类*do*保存对外部类的引用.它通常不可见但它就在那里 (3认同)

Ste*_*n C 20

如果有任何性能差异应该很少.如果存在差异,它将处于不值得担心的水平.

IMO,您应该专注于编写可读和可维护的代码,并忽略"微观"性能问题,直到您有明确的证据表明它们是重要的...基于对应用程序进行概要分析.

(对于记录,当匿名内部类引用final封闭范围中的a时,这是通过隐藏的构造函数参数和隐藏的实例属性在字节码级别实现的.字节码与您从中获得的字节码几乎相同你的其他实现.)


pol*_*nts 18

重要的是要意识到匿名类仍然是在编译时已知并完全编译的类.例如,你在循环中定义一个匿名类体,可能有很多方法和字段等,这并不意味着运行时必须在每次迭代时编译该类型.

因此,两种方法之间的任何性能差异都可以忽略不计.需要考虑的重要因素包括可读性,可重用性,可测试性等.


Pet*_*ont 5

当实例化一个匿名类的许多实例时,我实际上已经注意到了性能的显着下降。

考虑是否可能是由于本地类是静态的,我删除了它,这没有什么区别。

就我而言,我做了1000次选择3次,即499,500次。具有本地类的版本(无论是否为静态)花费了26秒,而具有匿名功能相同的类的版本花费了2分20秒。

  • 如果您提供基准代码来支持这一点,将会很有帮助。 (2认同)

Det*_*Det 5

关于性能,您应该考虑是否应该创建内部类。

不良做法的一个例子是:

public List<String> someMethod() {
       return new ArrayList<String>() {{
                      add("Item one");
                      add("Item two");
              }};
}
Run Code Online (Sandbox Code Playgroud)

虽然这种语法便利乍一看很聪明,但这(通常不被注意)创建了一个匿名内部类,其对象保持对外部实例的引用。由于此对象也作为 someMethod 的结果值提供给外部,因此您无法确定您的调用者对这个列表做了什么。如果他将结果 ArrayList 实例放入某个静态变量中,您当前的 Object 也将永远保留!

  • 询问三年前的评论?好吧,从 Java 7 开始,这将是 return Arrays.asList("Item one", "Item Two"); 不是吗? (2认同)