A sample program

The program shown in Listing 1 is designed specifically to illustrate various characteristics of member classes.

Listing 1. The program named InnerClasses06.java.
/*File InnerClasses06.java
Copyright 2003 R.G.Baldwin

Rev 6/22/03

Illustrates the use of member classes.  Class B
is a member class of class A.  Class C is a
member class of class B.  Class D is a private
member class of class C.  An object is
instantiated from class A, which makes
it possible to instantiate an object of the
member class named B.  According to Flanagan,
this causes the object of the Class B to be
internally associated with the object of the
class named A.  The object of class B
is used to instantiate an object of the member
class named C.  This object is internally
associated with the object of the class B.

When the object of the class C is instantiated,
the constructor for that class instantiates
separate objects of the classes named A and B and
also instantiates an object of the private member
class named D.  The new and separate object of
the class B continues to be internally associated
with the original object of the class A.

A variety of operations are performed from within
methods belonging to the object of the Class C to
illustrate the various characteristics of objects
instantiated from member classes.  Comments in
the code explain the purpose of each of those
operations.

The compilation of this program produces the
following class files:

A$B$C$D.class
A$B$C.class
A$B.class
A.class
InnerClasses06.class
X.class

The output from this program is shown below:

In xstr for A, objCntA = 1
In xstr for B, objCntB = 1
In xstr for C, objCntC = 1
Construct obj of private class D.
  Private class file name: A$B$C$D
In xstr for A, objCntA = 2
In xstr for B, objCntB = 2
-1-
In cShow, objNumber = 1
In cShow, cVar = 3
-2-
In bShow, bVar = 2
In bShow, objNumber = 1
In aShow, aVar = 1
In aShow, objNumber = 1
-3-
In aShow, aVar = 1
In aShow, objNumber = 1
-4-
A$B$C
A$B$C
A$B$C
A$B$C
A$B$C
-5-
A$B
A$B
-6-
A
-7-
In cShow, bVar = 20
A$B
In cShow, aVar = 10
A
-8-
In bShow, bVar = 20
In bShow, objNumber = 2
In aShow, aVar = 1
In aShow, objNumber = 1
-9-
In aShow, aVar = 10
In aShow, objNumber = 2
-10-
className = C
toString in Class C
className = X
toString in Class X


Tested using SDK 1.4.1 under WinXP
************************************************/

public class InnerClasses06{
  public static void main(String[] args){
    //Instantiate an object of the member class
    // named C.  Note that it is necessary to
    // instantiate objects of the enclosing
    // classes as well.  Then invoke the public
    // method named cShow on the object of the
    // class named C.
    new A(1).new B(2).new C(3).cShow();
  }//end main
}//end class InnerClasses06
//=============================================//

//This class will be extended by class
// C, which is a member of class B,
// which is a member of class A.  This
// will illustrate that the inheritance
// hierarchy is independent of the containment
// hierarchy.
class X{//extends Object by default
  protected String className = "X";

  //Override the toString method
  public String toString(){
    return "toString in Class X";
  }//end overridden toString
}//end class X
//=============================================//

class A{
  private int aVar;
  private static int objCntA = 0;
  //Cannot place static variable in inner class.
  // Place it here instead.
  private static int objCntB = 0;
  //Cannot place static variable in inner class.
  // Place it here instead.
  private static int objCntC = 0;
  private int objNumber = 0;

  A(int val){//top-level class constructor
    aVar = val;
    objCntA++;//Increment object counter
    //Record the number of the object being
    // instantiated
    objNumber = objCntA;
    System.out.println(
          "In xstr for A, objCntA = " + objCntA);
  }//end constructor
  //-------------------------------------------//

  private void aShow(){
    System.out.println(
                     "In aShow, aVar = " + aVar);
    System.out.println(
           "In aShow, objNumber = " + objNumber);
  }//end aShow
  //===========================================//

  //Note that this class is defined internal to
  // class A.
  class B{//member class of A
    private int bVar;
    private int objNumber = 0;

    B(int val){//constructor
      bVar = val;
      //Increment static variable in top-level
      // class
      A.objCntB++;
      //Record the number of the object being
      // instantiated
      objNumber = objCntB;
      System.out.println(
          "In xstr for B, objCntB = " + objCntB);
    }//end constructor
    //-----------------------------------------//

    private void bShow(){
      System.out.println(
                     "In bShow, bVar = " + bVar);
      System.out.println(
           "In bShow, objNumber = " + objNumber);
      //Invoke the private method named aShow
      // belonging to the internally associated
      // object of class A.
      aShow();
    }//end bShow
    //=========================================//

    //Note that this class is defined internal to
    // class B.
    class C extends X{//member class of B
      private int cVar;
      private A refToA;
      private B refToB;
      private String className = "C";
      private int objNumber = 0;

      C(int val){//constructor

        cVar = val;
        //Instantiate separate objects of the
        // enclosing classes B and C.  Will
        // display info about them later.  The
        // object of the Class B is internally
        // associated with the original object of
        // the class A.

        //Increment the object counter in the
        // top-level class.
        A.objCntC++;
        objNumber = A.objCntC;
        System.out.println(
                      "In xstr for C, objCntC = "
                                    + A.objCntC);

        //Instantiate object of private member
        // class named D.
        new D();

        //Instantiate objects of enclosing
        // classes named A and B.

        refToA = new A(10);
        refToB = new B(20);

      }//end constructor

      public void cShow(){
        System.out.println("-1-");//separator
        //Display private member variables
        // belonging to this object.
        System.out.println(
           "In cShow, objNumber = " + objNumber);
        System.out.println(
                     "In cShow, cVar = " + cVar);
        System.out.println("-2-");//separator
        //Invoke the private method named bShow
        // in the internally associated object of
        // class B.  This method will,
        // in turn invoke the private method
        // named aShow in the object of the class
        // named A to which the object of the
        // class named B is internally
        // associated.
        bShow();
        System.out.println("-3-");//separator

        //Invoke the private method named aShow
        // in the internally associated object
        // of class A.
        aShow();
        System.out.println("-4-");//separator

        //Illustrate the syntax required to gain
        // access to the objects instantiated
        // from the classes named C, B, and A.
        // The first five statements produce the
        // same result.  The class names that are
        // displayed match the names of the class
        // files produced by the compilation
        // process.
        System.out.println(getClass().getName());
        System.out.println(
                      this.getClass().getName());
        System.out.println(
                    C.this.getClass().getName());
        System.out.println(
                  B.C.this.getClass().getName());
        System.out.println(
                A.B.C.this.getClass().getName());
        System.out.println("-5-");//separator

        //The following two statements produce
        // the same output
        System.out.println(
                    B.this.getClass().getName());
        System.out.println(
                  A.B.this.getClass().getName());
        System.out.println("-6-");//separator


        System.out.println(
                    A.this.getClass().getName());
        System.out.println("-7-");

        //Display private instance variables and
        // class names belonging to separate
        // objects instantiated from the
        // enclosing classes named A and B.
        System.out.println(
              "In cShow, bVar = " + refToB.bVar);
        System.out.println(
                    refToB.getClass().getName());

        System.out.println(
              "In cShow, aVar = " + refToA.aVar);
        System.out.println(
                    refToA.getClass().getName());
        System.out.println("-8-");

        //Invoke the private bShow method on the
        // separate object instantiated from the
        // class named B in order to show the
        // object to which that object is
        // internally associated.  Even though
        // this object was instantiated from
        // within the constructor for the class
        // named C, it is internally associated
        // with the object of the class A that
        // was originally used to instantiate the
        // object of class C.
        refToB.bShow();
        System.out.println("-9-");

        //Invoke the private aShow method on the
        // separate object instantiated from the
        // class named A.
        refToA.aShow();
        System.out.println("-10-");

        //Illustrate the inheritance hierarchy to
        // which class C belongs by
        // getting and displaying the variable
        // named className from both the C class
        // and the X class.  Note that the
        // variable is protected in the X class.
        // Also invoke the overridden toString
        // methods belonging to the object
        // instantiated from class C.
        // One version is overridden in the class
        // named X and the other version is
        // overridden in class C.  Note
        // that the inheritance hierarchy is
        // totally independent of the containment
        // hierarchy.
        System.out.println(
                     "className = " + className);
        System.out.println(toString());
        //Note: cannot access private variable in
        // superclass named X. Must be protected,
        // package, or public.
        System.out.println(
               "className = " + super.className);
        System.out.println(super.toString());
      }//end cShow
      //---------------------------------------//

      //Override the toString method
      public String toString(){
        return "toString in Class C";
      }//end overridden toString
      //=======================================//

      private class D{//member class of C
        D(){//constructor
          System.out.println(
            "Construct obj of private class D.");
          System.out.println(
                    "  Private class file name: "
                    + this.getClass().getName());
        }//end constructor
      //Note that all four class definitions end
      // here in the proper nested order.
      }//end class D
    }//end class C
  }//end class B
}//end class A
File: be.htm [Next] [Prev]