CS102: Inner Classes and Adapters

Copyright © 1999, Kenneth J. Goldman

Inner Classes

Sometimes we define a class whose purpose is only to "help out" another class.
For example, the ListItem class for a LinkedList class. In that kind of situation,
it would be nice if the helper class didn't stand on its own, but instead was more closely
assoiciated with the class itself.

 So far, all classes we have defined have been "top level classes." In other words,
as far as the Java compiler is concerned, the classes are independant and
exist on there own.

We have done some things in CS101 and CS102 to capture the sense that two classes
belong together. Namely, we have

  • Put the classes in the same file (only one is public)
  • Put the class in the same package
  • These are helpful, but neither really says that one class is somehow "part of" another class.
    To express this kind of relationship between classes, Java programmers can use something
    called "inner classes."

    There are four varieties of inner classes. We'll take a look at each one and give some examples.
     

    Nested Top Level Classes

    This is a class defined as a static class member. Its still really a top-level class, but from outside
    its name is prefixed with the name of the containing class seperated by a dot. Access to the class
    can be controlled through protection modifiers.
    For example:
     
      public class Animation extends Component{
        public Animation(....){
          ....
          addMouseListener( new AnimationRequestHandler() );
          ....
        }
        public void beginAnimation(){                             //Note 1
          ....
        }

        private static class AnimationRequestHandler extends MouseAdapter{
         

          public void mouseClicked(MouseEvent e){
           
            ((Animation)(e.getSource()))).beginAnimation();     //Note 2
          }
        }
      }
    Note 1: beginAnimation() must be public becauce AnimationRequestHandler is a top level class
    and has no special access to methods in Animation,  i.e. the innner class AnimationRequestHandler
    can access only public methods and public instance variables of the Animation class, not private ones.

    Note 2: Just like with any other method, you must use objectName.methodName() notation for
    beginAnimation().

    Member Classes

    These are not top level classes - they are declared like instance variables and methods (not static)
    and each instance of a member class has a corresponding instance of the containing class (usually the
    one that created it).

    Instances of member classes have access to the instance variables and methods of the containing
    class (and vice versa), as well as other member class instance variables and methods created by the
    original class. (Bug: some compilers don't allow access to private members)
    For example:
     

      public class Animation extends Component{
        public Animation(....){
          ....
          addMouseListener( new AnimationRequestHandler() );
          ....
        }
        void beginAnimation(){            //Note 1
          ....
        }

        private class AnimationRequestHandler extends MouseAdapter{
         

          public void mouseClicked(MouseEvent e){
           
            beginAnimation();     //Note 2
          }
        }
      }
    Note 1: beginAnimation() does not need to be public becauce AnimationRequestHandler is member
    class and has access to methods in Animation,  i.e. the member class AnimationRequestHandler
    can access any method or instance variable of the Animation class.

    Note 2: This time beginAnimation() can be called without a source because there is only one object it
    could belong to.

    Technical Note: Member classes can't contain any static members and they can't have the same name
    as any containing class or package.
     

    Local Classes

    These are similar to member classes, except that they are declared within a method, and have access
    to final local variables within that scope and they are only visible and usable within that scope.

    For Example:
     

     public class Animation extends Component{
    public Animation(....){
     
    class AnimationRequestHandler extends MouseAdapter{
     
    public void mouseClicked(MouseEvent e){
     
    beginAnimation();
    }
    }
    ........
    addMouseListener( new AnimationRequestHandler() );
    ........
    }
    void beginAnimation(){            //Note 1
    ......
    }
    }
    Local classes have the same restrictions as member classes: local classes can't contain any static
    members and they can't have the same name as any containing class or package.

    Anonymous Classes

    These are similar to local classes, except they have no names. Instead, they are defined within the
    expression that intantiates them.

    Anonymous classes either

  • extend a class, or
  • implement an interfance (and extend Object)
  • It is typical to extend an adapter, as in the following example:
     
      public class Animation extends Component{
        public Animation(....){
          ....
          addMouseListener( new MouseAdapter(){          //Note 1
            public void mouseClicked(MouseEvent e){
              beginAnimation();
            }
          });
          ........
        }
        void beginAnimation(){
          ......
        }
      }
    Note 1: MouseAdapter is the name of the class being extended or interface being implemented.
    Any parameters to the contstucter for mouseAdapter need to be included.

    An anonymous class inherits its contructor because it can't define its own.
    An anonymous class has no name.
    An anonymous class has no protection modifiers - it has no name, so you can't access it from outside anyway.