29

Is there any difference in efficiency (e.g. execution time, code size, etc.) between these two ways of doing things?

Below are contrived examples that create objects and do nothing, but my actual scenarios may be creating new Threads, Listeners, etc. Assume the following pieces of code happen in a loop so that it might make a difference.

Using anonymous objects:

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
            }
        };
    }
}

Defining a class first:

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() {}
};
Bacteria
  • 8,406
  • 10
  • 50
  • 67
Phil
  • 5,595
  • 5
  • 35
  • 55
  • 3
    You should do what you believe is the clearest and easiest to understand, the performance difference should be much much smaller than the work you do in doWork() so it won't make a difference. If I were to estimate the difference, I would expect about 10 nano-seconds. – Peter Lawrey Jun 12 '10 at 10:46
  • Unless you were doing performance critical code and your lecture doesn't hold – LegendLength Jun 07 '17 at 12:09

6 Answers6

44

The only practical difference between the anonymous classes and the top-level classes is that the anonymous classes will hold an implicit reference to the outer class.

This won't manifest itself in performance, but will impact you if you ever serialise these classes.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • 13
    It will impact performance if it doesn't make sense for references to the outer class to be kept alive -- especially when the garbage truck rolls around. You'll be collecting more garbage at once rather than letting the outer class fall out of scope as needed. Not a huge difference but it is not to be overlooked. – dcow Aug 14 '13 at 18:52
  • 1
    @dcow care to explain, I didn't exactly catch your drift when you said '... for references to the outer class to be kept alive' Did you mean if the inner class keeps references to the outer class? – Cu7l4ss Jun 23 '14 at 12:12
  • 3
    @Cu7l4ss - the inner classes *do* hold a reference to the outer class. It's not normally visible but it is there – Brian Agnew Jun 23 '14 at 13:04
20

There should be little if any performance difference. If there is a difference it will be at a level where it is not worth worrying about.

IMO, you should focus on writing code that is readable and maintainable, and ignore "micro" performance issues until you have clear evidence that they are significant ... based on profiling the application.

(For the record, when an anonymous inner class refers to a final in an enclosing scope, this is implemented at the bytecode level by means of hidden constructor arguments and hidden instance attributes. The bytecodes will be almost the same as the bytecodes that you get from your other implementation.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
18

It's important to realize that anonymous classes are still classes that were known and fully-compiled at compile time. The fact that, say, you're defining an anonymous class body, perhaps with many methods and fields etc within a loop, doesn't mean that the runtime has to compile that type on every iteration.

Thus, any difference in performance between the two approaches are negligible. The important factors to consider are things like readability, reusability, testability, etc.

polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
5

I actually HAVE noticed a significance performance hit when instantiating many instances of an anonymous class.

Thinking if might be due to the local class being static I removed that and it made no difference.

In my case, I was doing something 1000 choose 3 times which is 499,500. The version with the local class (regardless of static or not) took 26 seconds and the version with the anonymous functionally identical class took 2 minutes 20 seconds.

PeterVermont
  • 1,922
  • 23
  • 18
  • There are many things to consider as nested classes may also cause additional side-effects if used heavily. For instance, any attempt to access private members or methods of another object (such as the outer one) will end up in a public method (a simple getter) being generated and used instead. That is something you should keep in mind when nesting logic. Don't have the link for this, but found it some time ago in JVM specification. – Pijusn Jun 28 '14 at 17:12
  • 3
    It would be helpful if you provided your benchmark code to support this. – Stephen C Jun 07 '17 at 12:20
5

Regarding performance you should consider if an inner class should be created or not at all.

An example for bad practice is something like:

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

While this syntactical convenience looks smart at a first glance, this (often unnoticed) creates an anonymous inner class whose object keeps a reference to the outer instance. As this object is also given to the outside as result value of someMethod, you cannot be sure what your caller does with this list. If he puts the resulting ArrayList instance into some static variable, your current Object will be kept forever too!

Det
  • 425
  • 4
  • 8
  • Then how do you return the list? what is your proposal for better practice? Thanks – jlanza Oct 03 '17 at 11:13
  • 2
    Asking on a three years old comment? Ok, well, since Java 7 that would be return Arrays.asList("Item one", "Item two"); Wouldn't it? – Det Oct 04 '17 at 17:02
1

Speculating about code performance is an excellent way of wasting your time. Nothing compares to actually benchmarking the code. If you're worried about performance, measure the code. If you suspect that your code is sub-optimal, profile the code to figure out where the time is spent, then try to improve those parts. At this time it may be appropriate to actually study the byte code to see if that may give you a hint which implementation is more efficient.

When you've done that, measure the code again to make sure that you didn't make things worse, for example by making the code uglier and more difficult to maintain.

JesperE
  • 63,317
  • 21
  • 138
  • 197