Inner Classes: Named and Anonymous

Home Up Search Java 2 API C++ Resources

Named Inner Classes

  •  An inner class is a class defined inside another class.
  • An inner class object is scoped not to the outer class, but to the instantiating object.   
    • Even if the inner class object is removed from the outer class object that instantiated it, it retains the scoping to its creator.
    • If an object has a reference to another object's ("parent object"'s) inner class object, the inner class object is dealt with by that object as a separate, autonomous object, but in fact, it still has access to the private variables and methods of its parent object.
    • An inner class instantiation always remembers who it's parent object is and if anything changes in the parent object (e.g. one of its property's value changes),  that change is reflected in all its inner class instantiations. 
  • Inner classes are very useful in factory pattern situations.

Syntax:

[normal class declaration]
{
     [scoping] class [inner class's name] [extends ....] [ implements ...]
     {
          // properties and methods of the inner class
     }

     // rest of properties and methods of parent class 
}

 

Anonymous Inner Classes

  • Anonymous inner class:  An inner class with no name.
  • Example: actionPerformed events utilize the Observer-Observable pattern -- An instance of the observer is added to the observable.    JBuilder creates an anonymous inner class to give to the button as its ActionListener.
  • Anonymous inner classes are very similar to named inner classes:
    • Anonymous inner classes can override methods of the superclass.
    • Anonymous inner classes are scoped inside the private scoping of the outer class.  They can access the internal (private) properties and methods of the outer class.
    • References to an inner class can be passed to other objects.  Note that it still retains its scoping.
  • But there are some important differences:
    • Anonymous inner classes must use the no parameter constructor of the superclass.
    • Since an object made from the inner class has a "life" independent of its outer class object,  there is a problem with accessing local variables, especially method input paramenters.  
    • Two ways to pass initializing parameters to an inner class:
      • Initialize a property that the inner class then uses -- properties have the cross-method-call persistence that local variables lack.
      • Make the local variable "final" -- compiler will automatically transfer the value to a more persistent portion of the computer memory.   Disadvantage:  the value cannot be changed.
  • Usages:
    • Very useful for controlled access to the innards of another class.
    • Very useful when you only want one instance of a special class.

Syntax:


[variable_type_superclass =]  new superclass_name()  {
                                                                // properties and methods
                                                  }  [;]

 

Examples:

Timer object with anonymous ActionListener:

Timer timer = new Timer( 200, new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
         // do something
    }
});

Initialization using a final input parameter  (each Object made will have the name that was used when makeObj() was called to make it.)

public MyClass makeObj(final String name)
{
     return new SubClassOfMyClass() {
           public String toString()
           {
                 return "My name is "+name;
           }
     };
}

Initialization using final local variable

public Object makeObj(String name)
{
     final String objName = "My name is " + name;
 
     return new Object() {
           public String toString()
           {
                 return objName;
           }
     };
}

Initialization using initialization block

public Object makeObj(String name)
{
     
     return new Object() {

           String objName;

           {
                objName = "My name is " + name;
            }

            public String toString()
           {
                 return objName;
           }
     };
}