Anonymous Inner Class Techniques

COMP 310    Java Resources  Eclipse Resources

Anonymous inner classes are extremely useful in OOP because of their ability to close over a dynamic environment thus enabling one to build objects on the fly with different behaviors simply because when they were instantiated they captured different environments in their closures.   Click here for basic information on Inner and Nested Classes.

Always remember that an anonymous inner class is an object, not a class.  Technically, it is a singleton instance of a sub-class/implementation of its superclass/interface.   It is not required that you assign an anonymous inner class to a variable -- you only need to do that if you intend to reference it more than once.

Here's an example of an anonymous inner class declaration with lots of bells and whistles:

/**
 * Superclass can be class or interface
 * Notice how call to superclass constructor is done, if parameters are needed.
 * param1, param2, etc are parameters to the superclass constructor, 
 * ala super(param1, param2, etc)
 */
SuperClass instance = new SuperClass(param1, param2, etc) {
    FieldType field;  // private field for internal use
    
    // "Initializer block" = anonymous constructor
    {
        // runs after the superclass constructor
        // No need to pass in parameters -- why?
    }
    
    /**
     * Overriden method of superclass/interface provides public behavior
     */
    public ReturnType overridenMethod(Type1 t1, Type2 t2) {
        // desired code
    }
    
    /**
     * private method for internal use.
     */
    Stuff internalMethod(){
       // code
    }
};

Notes:

Things to remember:

 

Referencing Enclosing Anonymous Inner Classes

The Java syntax enables one to reference the class instance one is currently in, "this", and the outermost enclosing class instantance, "Classname.this"  (where "Classname" is the name of outermost named class.).   Unfortunately, there is no Java syntax construct for referencing an enclosing anonymous inner class.  

Technically, "this" is just a special field in a class that holds a reference to the instance of the object.  Thus, to get around this problem, all we need to do is to manually create a field to mimic the "this" field that a subsequently nested anonymous inner class can reference:

// An instance of an anonymous inner class of type "EnclosingClass"
new EnclosingClass() {

   EnclosingClass thisEnclosingClass = this;    // A field that captures the reference to this anon. inner class instance.  
   
   // somewhere inside the EnclosingClass anonymous inner class declaration
   // there is a declaration of an anonymous inner class of type "EnclosedClass"...
   ... new EnclosedClass() {
   
           //  "thisEnclosingClass" is in scope here and references the enclosing anonymous inner class instance.
   
   };
   ...
}  

There is nothing special about or any naming requirements for the field that is created to hold the reference to the enclosing instance ("thisEnclosingClass" above).  Choose a name that means something.

This technique can be repeated to name as many levels of nested anonymous inner classes as desired.   Be sure to use unique names for each anonymous inner class!

This technique is particularly helpful when wrting recursive algorithms with helpers that need to recur on a nested helper.

 

Here's another example with more levels:

	
class MyClass {
	...

	new InnerClass1() {
		InnerClass1 thisInnerClass1 = this;   // self-reference is available when this field is being defined.
		...

		new InnerClass2() {
			InnerClass2 thisInnerClass2 = this;   // This "this"  is for this instance of InnerClass2, not InnerClass1
			...

			new InnerClass3(){
				...
				
				/**
				All levels of the nested anonymous inner classes can now be referenced:
				
				this ==> the instance of this InnerClass3
				thisInnerClass2 ==> the instance of the enclosing InnerClass2
				thisInnerClass1 ==> the instance of the enclosing InnerClass3
				MyClass.this ==> the instance of the enclosing MyClass
				
				*/
				
				...
			}
			...
		
		}
		...
	
	}
	...

} 
	

 

 

 

 

 

© 2020 by Stephen Wong