Anonymous Inner Class

In the JavaLanguage, this is an anonymous specialization of some class or interface. Because it is anonymous and inline, it is necessarily an inner class - i.e., defined within some other class. The following is a popular use of anonymous inner classes:

 addWindowListener( 
     new WindowAdapter() {
         public void windowClosing( WindowEvent e ) {
             System.exit(0); 
         } 
     });
This is the same as the following non-anonymous inner:

 public class WindowClosingAdapter extends WindowAdapter {
     public void windowClosing( WindowEvent e ) {
         System.exit(0);
     } 
 }

...

addWindowListener( new WindowClosingAdapter() );
AnonymousInnerClasses can also be used to create something like closures in the JavaLanguage. However they do not "close over" the lexical environment so they aren't TrueClosures?. (They can capture the value of local variables, but they do not have access to the variable binding so they can't change the original variable. Which Java makes quite clear by only allowing InnerClasses to refer to local variables that have been declared final (so no-one can change them)).

Yes. Quite true. So you put the variable in a class -- and then you can change it. ;->
 class IntHolder {
    public int i;
 }

The second example seems much clearer than the first. Naming a class makes the code more readable, even if it requires some extra keystrokes.
Another use of the anonymous inner class is as a shortcut convenience for declaring a local inner class and creating an instance of that class.

(Source: http://w3.one.net/~jweirich/java/compuware/java2/anoninnerclassexample.html) (see Source for Inner.java and Transform Declaration)

        private static LinkedList multiple (LinkedList aList, final int factor) {
	return aList.collect ( new Transform() {
	    public int calculate (int n) { return n*factor; }
	});
    }
In this example, the collect() method returns a new list based upon applying a transformation to each element of an existing list. The transformation is specified by the Transform interface. The multiple() method creates an implementation of Transform and an instance in one step. Since we only need one object of this type of transform, we do not need to give the subclass a name.

Here, the syntax for instantiating the anonymous inner class is
    Transform t = new Transform () { /* implementation code */ }


I've used AnonymousInnerClasses to make VirtuallyInitializedAccessors to create inexpensive objects whose lifetimes are just long enough to render a JavaServerPage. (3/28/01)
   mailto:kimball_sampson@discovery.com


AnonymousInnerClasses may take a bit to get our heads around, but once we are comfortable with them, they turn into very powerful tools. However, I did once hear MartinFowler use the word "abominations" when describing the way SmallTalkers tend to use anonymous inners in java. <grin>.

Also, look out for problems with JavaSerialization with AnonymousInnerClasses.


"Inner classes are unnecessary. ...to the point of being obscene. (And yes, I use them all the time. ;-)" -- JeffGrigg (from http://groups.yahoo.com/group/extremeprogramming/message/78765 )


AnonymousInnerClasses can do more than just override methods or couple to the containing class. They have a couple of non-obvious but useful features that help minimise the clutter of named but otherwise trivial InnerClasses:

This makes possible some nifty tricks, particularly in factory methods:
   Object newLightlySpecialisedObject(final String p){
     final String l="Local constant";
     return new Object(){
       String f="Non-final field";
       String newStringValue(){
         f=valueFromProtectedMethod();
         return "parameter="+p+", local="+l+", field="+f;
       }
       String toString(){return newStringValue();}
     };
   }
If you absolutely have to create a named InnerClass, see if it can be local, i.e., defined inside the method that uses it. It's sometimes worth naming a potentially anonymous class in this way, just to make it easier to spot in stack traces.

The serialization problem mentioned above applies to all non-static inner classes. Serializing the class implies serializing the enclosing class as well, because the hidden reference cannot be declared transient.

-- DavidWright


See also: InnerClass, BlocksInJava
CategoryJava CategoryClosure

EditText of this page (last edited November 9, 2007) or FindPage with title or text search