2

I have done some searching on the difference in implementing a closure using an anonymous class and a local class. I am trying to figure out all the differences between the two so I know which method is better in which situations.

Correct me if I am wrong:

  • The anonymous class has a class instance and object instance created each time a new instance is created.
  • The local class has only an object instance create each time a new instance is created.

Therefore, is there ever a time or place where I should use an anonymous class over a local class?

EDIT: It appears there is no real difference between the two, just depends on style and if you want to reuse the class.

To clarify what I mean here is an example of what I am talking about:

public class ClosureExample {
interface Function {
    void func(int value);
}

public static void main(final String[] args) {
    final Function local1 = localClassClosure("Local1");
    final Function local2 = localClassClosure("Local2");

    final Function anonymous1 = anonymousClassClosure("Annonymous1");
    final Function anonymous2 = anonymousClassClosure("Annonymous2");

    for (int i = 0; i < 3; i++) {
        local1.func(i);
        local2.func(i);
        anonymous1.func(i);
        anonymous2.func(i);
    }
}

private static Function localClassClosure(final String text) {
    // Local class name is irrelevant in this example
    class _ implements Function {
        @Override public void func(final int value) {
            System.out.println(text + ":" + value);
        }
    }
    return new _();
}

private static Function anonymousClassClosure(final String text) {
    return new Function() {
        @Override public void func(final int value) {
            System.out.println(text + ":" + value);
        }
    };
}
}

Hopefully, someone can explain in detail this subtle difference and which method should be used in which situations.

Jyro117
  • 4,519
  • 24
  • 29
  • 1
    Why on earth is an underscore a class name? – Lews Therin Sep 23 '12 at 00:15
  • What do you mean by *class instance* and *object instance*? – Sujay Sep 23 '12 at 00:16
  • By class instance, I'm referring to the class being loaded into the JVM by the class loader. – Jyro117 Sep 23 '12 at 00:18
  • Note that the pre-Java 8 "closures" discussed in this Question are not true closures in the normally accepted sense. The difference is that the variables in the enclosing scope must all be `final`. This allows the closure behaviour to be simulated by adding shadow copies of these variables to the inner / anonymous class as hidden variables. – Stephen C Sep 23 '12 at 00:48

4 Answers4

2

This piqued my interest, and I broke out JD-GUI to look at the decompiled classes. There is actually no difference at all between the two anonymous inner classes after compilation:

localClass:

class ClosureExample$1t implements ClosureExample.Function{
  ClosureExample$1t(String paramString){
  }

  public void func(int value){
    System.out.println(this.val$text + ":" + value);
  }
}

anonymousClass:

class ClosureExample$1 implements ClosureExample.Function{
  ClosureExample$1(String paramString){
  }

  public void func(int value){
    System.out.println(this.val$text + ":" + value);
  }
}

Both methods are valid ways of implementing an anonymous inner class, and they seem to do the exact same thing.

EDIT: I renamed the _ class to t

monitorjbl
  • 4,280
  • 3
  • 36
  • 45
  • Ah, didn't think of looking at the classes after decompiling. Yes, very interesting there is actually no difference! – Jyro117 Sep 23 '12 at 00:36
0

I am pretty sure there is nothing like object instance, just class instance . So yes an object is created for both local and anonymous types.. The difference however is you can't reuse the anonymous class (except through the way you used it in your method - which works but not really maintainable), so you use it when whatever you are doing is a one off thing. For example with event listeners.

I would prefer named types to anonymous types though.

You might find this useful

EDIT: You will find my question here useful.

Community
  • 1
  • 1
Lews Therin
  • 10,907
  • 4
  • 48
  • 72
  • I've realized where my misunderstanding is, there is no actual difference and I had read somewhere a new class is created every time an anonymous class instance is created. This isn't the case. – Jyro117 Sep 23 '12 at 00:30
  • 2
    The class is only created once. A class is being generated by the compiler you are just unaware of the name. It could be something like "RandomClassABlah" – Lews Therin Sep 23 '12 at 00:31
  • I didn't realize that until I just printed out the class names being created: ClosureExample$1_ ClosureExample$1_ ClosureExample$1 ClosureExample$1 I was expecting the second anonymous class to be ClosureExample$2 – Jyro117 Sep 23 '12 at 00:33
  • @Jyro117 You reminded me of the same problem I had. See my update. – Lews Therin Sep 23 '12 at 00:37
0
  1. The local class object is faster at initialization (because the class is already in memory at startup)
  2. The anonymous class object less memory consuming (because of the lazy evaluation)

Notice : Because java is not a real functional language. Anonymous classes will be pre-evaluated and even stored in class files. So really there wont be much difference.

In a functional language, like scheme :

(define inc (lambda (a) (lambda () (+ 1 a))))
(display ((inc 5))) 

The function (lambda () (+ 1 a)) will be actually recreated at each anonymous call like ((inc 5)). This is the concept behind anonymous classes.

As opposed to:

(define inc (lambda (a) (+ 1 a)))
(display (inc 5)) 

Where (lambda (a) (+ 1 a)) will be stored in memory at compile time, and the call to (inc 5) will only reference it. This is the concept behind local classes.

Eli Turchinsky
  • 331
  • 2
  • 8
  • So after initialization, there is no difference between the two methods? – Jyro117 Sep 23 '12 at 00:31
  • Pretty much.. because as far as i remember java actually creates class files at runtime even for anonymous classes. Java is not really a functional language. In functional languages , the difference between this two cases is a basic concept. – Eli Turchinsky Sep 23 '12 at 00:37
0

Just a note about this:

Therefore, is there ever a time or place where I should use an anonymous class over a local class?

If you need to quickly setup an event listener [e.g. a KeyListener] inside a component, you can do like this:

addKeyListener(new KeyListener(){

    public void keyPressed(KeyEvent ke){ ... }

    // further implementation here

});

Though it won't be reusable at all.

moonwave99
  • 21,957
  • 3
  • 43
  • 64