Java匿名类效率的含义

时间:2010-06-12 10:32:40

标签: 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
            }
        };
    }
}

首先定义一个类:

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() {}
};

6 个答案:

答案 0 :(得分:39)

匿名类和顶级类之间的唯一实际区别在于匿名类将包含对外部类的隐式引用。

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

答案 1 :(得分:19)

性能差异应该很小。如果存在差异,它将处于不值得担心的水平。

IMO,您应该专注于编写可读和可维护的代码,并忽略“微观”性能问题,直到您清除证明它们是重要的......基于对应用程序进行概要分析。 / p>

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

答案 2 :(得分:18)

重要的是要意识到匿名类仍然是在编译时已知且完全编译的类。事实上,比如说,你定义了一个匿名类体,可能在循环中有许多方法和字段等,这并不意味着运行时必须在每次迭代时编译该类型。 / p>

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

答案 3 :(得分:4)

我实际上已经注意到在实例化匿名类的许多实例时出现了重要性。

如果可能是由于本地课程是静态的,我将其删除并且没有任何区别。

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

答案 4 :(得分:4)

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

不良做法的一个例子是:

public List<String> someMethod() {
       return new ArrayList<String>() {{
                      add("Item one");
                      add("Item two");
              }};
}

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

答案 5 :(得分:0)

推测代码性能是浪费时间的绝佳方式。没有什么比实际基准测试代码。如果您担心性能,衡量代码。如果您怀疑代码是次优的,分析代码以确定花费的时间,那么请尝试改进这些部分。此时,实际研究字节代码可能是合适的,看看是否可以提示哪些实现更有效。

当你完成后,再次测量代码,以确保你没有让事情变得更糟,例如让代码变得更丑,更难以维护。