Skip to content Skip to navigation

OpenStax_CNX

You are here: Home » Content » Java OOP: Local Classes

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Java OOP: Local Classes

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: Baldwin explains the various relationships that exist among local classes and their enclosing classes.

Preface

This module is one in a collection of modules designed for teaching ITSE2317 - Java Programming (Intermediate) at Austin Community College in Austin, TX.

(Editor's note: As you read this module, you will see that it was originally written around 2003. However, despite many improvements in Java since then, most of what was true then is still true in 2013.)

This module makes several references to my website, which is located at http://www.dickbaldwin.com/toc.htm .

Viewing tip

I recommend that you open another copy of this module in a separate browser window and use the following links to easily find and view the Images and listings while you are reading about them.

Images

Listings

Preview

What can you include in a class definition ?

There are several different kinds of items that can be included in a class definition. As you learned in the earlier modules in this series, the list includes:

  • Static variables
  • Instance variables
  • Static methods
  • Instance methods
  • Constructors
  • Static initializer blocks
  • Instance initializers

Can also contain other class definitions

As you learned in the previous module , a class definition can also contain the following three kinds of inner classes:

  • Member classes
  • Local classes
  • Anonymous classes

The previous module explained member classes. This module will explain local classes. The next module will explain anonymous classes.

What is a local class ?

A local class is a class that is defined within a block of Java code. While local classes are probably most frequently defined within methods and constructors, they can also be defined inside static initializer blocks and instance initializers.

As is the case for an object of a member class (discussed in the previous module ), an object of a local class must be internally linked to an object of the enclosing class. I will often refer to that object as the containing object, and make comments about the containment hierarchy.

A local class is truly an inner class, because an object of the local class cannot exist in the absence of an object of the enclosing class.

What about a local interface?

Interfaces defined within classes are implicitly static. This means that they are always top-level. There is no such thing as a member interface, a local interface, or an anonymous interface.

Why use local classes ?

Objects instantiated from local classes share many of the characteristics of objects instantiated from member classes. However, in some cases, a local class can be defined closer to its point of use than would be possible with a member class, leading to improved code readability.

Probably the most important benefit of local classes has to do with accessing the members of enclosing classes. Just like with member classes, methods of a local class have direct access to all the members of the enclosing classes, including private members. Thus the use of local classes can sometimes eliminate the requirement to connect objects together via constructor parameters.

(We will also see in the example program in this module that methods of a local class have direct access to protected members of the superclass of the enclosing class.)

Can be particularly useful when ...

A local class can be particularly useful in those cases where

  • There is no reason for an object of the local class to exist in the absence of an object of the enclosing class
  • There is no reason for an object of the local class to exist outside a method of the enclosing class
  • Methods of the object of the local class need access to members of the object of the enclosing class
  • Methods of the object of the local class need access to final local variables and method parameters belonging to the method in which the local class is defined

This module approaches local classes from a somewhat theoretical viewpoint. The next module will approach local classes from a more practical viewpoint, including a comparison between local classes and anonymous classes.

Local classes versus member classes

A local class has approximately the same relationship to a member class that a local variable in a method has to an instance variable of the class containing the method.

The scope of a local class

As is the case with local variables, the name of a local class is visible and usable only within the block of code in which it is defined (and blocks nested within that block). Further, the name of the local class is visible and usable only to code following the class definition within that block.

The methods of a local class can use any final local variables or method parameters that are visible from the scope in which the local class is defined.

Similar to member classes

As mentioned earlier, local classes have many characteristics in common with member classes. This includes access to private fields and methods in the containing class. The thing that separates local classes from member classes is the fact that local classes have access to local variables in the scope in which the local class is defined.

A big restriction

There is a big restriction, however, on the ability of methods of the local class to access local variables and method parameters. The methods in a local class can access local variables and method parameters only if they are declared final .

What does Flanagan have to say?

According to one of my favorite authors, David Flanagan, author of Java in a Nutshell, the methods in a local class don't really have access to local variables and method parameters. Rather, when an object of the local class is instantiated, copies of the final local variables and method parameters referred to by the object's methods are stored as instance variables in the object. The methods in the object of the local class really access those hidden instance variables. (See the later section entitled Smoke and mirrors.)

Thus, the local variables and method parameters accessed by the methods of the local class must be declared final to prevent their values from changing after the object is instantiated.

Restrictions on local classes

As with member classes, local classes cannot contain static members.

As with local variables, local classes cannot be declared public , protected , private , or static .

A local class cannot have the same name as any of its enclosing classes.

Smoke and mirrors

As I mentioned in the previous module, every class definition in a Java program, including nested top-level classes, member classes, local classes, and anonymous classes, produces a class file when the program is compiled. According to Flanagan,

"The Java Virtual Machine knows nothing about nested top-level classes and interfaces or the various types of inner classes. Therefore, the Java compiler must convert these new types into standard non-nested class files that the Java interpreter can understand. This is done through source code transformations that insert $ characters into nested class names. These source code transformations may also insert hidden fields, methods, and constructor arguments into the affected classes."

A reference to the containing object

For example, the compiler automatically inserts a private instance variable in the local class to hold a reference to the containing object. It also inserts a hidden argument in all constructors for the local class, and passes the containing object's reference to the constructor for the local class. The modified constructor saves that reference in the private instance variable of the object of the local class. Thus each object instantiated from the local class contains a private reference to the containing object.

Accessing private members

In those cases where it is necessary for an object of the local class to access private members of the containing object, the compiler automatically creates and uses accessor methods that make such access possible.

Similar to your code

The bottom line is that the code that is automatically produced by the compiler is probably very similar to code that you would write if you were writing the program using only top-level classes. The good news is that you don't have to write that extra code, and you don't have to maintain it. The extra code is written for you, and if you modify your class structure, the extra code is automatically modified accordingly.

Discussion and sample code

The paragraphs that follow will explain a program named InnerClasses07 . This program is designed specifically to illustrate various characteristics of local classes. I will discuss the program in fragments. A complete listing is shown in Listing 17 near the end of the module.

This program illustrates the use of local classes. The program consists of a total of five classes:

  • Four top-level classes named
    • InnerClasses07
    • A
    • X
    • Y
  • A local class named B.

When compiled, the program produces the class files shown in Image 1 . The file named A$1$B.class represents the local class. The remaining files in Image 1 represent the four top-level classes.

Class hierarchy

In the previous module, I explained that once you understand the class file naming convention, you can determine from the file names how top-level classes and member classes are structured. However, the situation isn't nearly so clear when it comes to local classes and anonymous classes. This will become more apparent in the next module, which combines local classes and anonymous classes.

Overall program structure and behavior

Containment hierarchy

The program named InnerClasses07 defines a local class named B inside an instance method named meth .

The method named meth is an instance method of a top-level class named A . The method named meth instantiates two separate objects of the local class named B , and calls a method named showB on each of them.

The method named showB displays certain data values that illustrate the characteristics of local classes, as well as the containment hierarchy among objects of the local class and an object of the containing class.

In this case, objects of the class named B are contained within an object of the class named A . (The class named A is an enclosing class of the class named B .)

Inheritance hierarchy

The top-level class named A extends the top-level class named X , (which in turn, extends Object ).

The class named B is contained in or enclosed by the top-level class named A , but extends the top-level class named Y , (which in turn, extends Object ).

There is no inheritance relationship between the classes X and Y (aside from their common superclass named Object ).

There is no inheritance relationship between the classes A and B .

The method named showB also displays data values that are intended to demonstrate that the inheritance hierarchy is independent of the containment hierarchy.

(Note that while the containment hierarchy of local classes is independent of the inheritance hierarchy, it is technically possible to establish an inheritance relationship between a local class and one of its enclosing classes. For example, by making a couple of minor modifications, it is possible to cause the local class B in this program to extend the enclosing class A instead of the top-level class Y .)

The controlling class

The entire controlling class named InnerClasses07 , including the main method and a static variable named baseTime , is shown in Listing 1 .

The static variable named baseTime is initialized with the current date and time in milliseconds (relative to January 1, 1970). This static variable is used later as a base to establish the relative points in time that certain activities occur during the execution of the program.

The main method

The main method shown in Listing 1 instantiates a new object of the class named A and calls the method named meth on that object.

This method will sequentially instantiate two separate objects of a local class named B that is defined inside the method named meth . Then the method named meth will call a method named showB on each of those objects, causing them to display data values that illustrate the characteristics of local classes.

The class named X

The top-level class named X is shown in Listing 2 .

The class named A extends this class to illustrate the difference between the inheritance hierarchy and the containment hierarchy. Note that this class defines and initializes a protected instance variable, which will be accessed later to illustrate the inheritance hierarchy.

(Somewhat surprisingly, you will also see later that this protected instance variable belonging to the superclass of the enclosing class A is also accessible by methods belonging to an object of the local class via the containment hierarchy.)

The class named Y

The top-level class named Y is shown in Listing 3 .

The local class named B extends this class to illustrate the difference between the inheritance hierarchy and the containment hierarchy.

Note that this class defines and initializes a protected instance variable. It also overrides the toString method, which is inherited from the Object class.

The instance variable and the overridden toString method will be accessed later to illustrate the inheritance hierarchy.

The class named A

The code in Listing 4 shows the beginning of the top-level class named A .

This code declares and initializes a private instance variable named aTime , which establishes the relative time that an object of class A is instantiated.

This private instance variable will be accessed directly by code belonging to an object of the local class B , which is contained by an object of the class A .

Listing 4 also shows the constructor for class A , which displays the time whenever an object is instantiated from class A .

The screen output

The code shown earlier in the main method of Listing 1 instantiates an object of class A . This causes the screen output shown in Image 2 .

(Note that the relative time output value on your system may be different, depending on the speed of your system and the impact of other applications that may be running concurrently.)

The private showA method

Listing 5 shows a private method named showA . This method displays the following information about an object instantiated from class A :

  • The relative time that the object was instantiated.
  • The value of the instance variable named xVar , which is an instance variable of the superclass of class A .
  • The name of the class file that represents the class named A .

Code in methods belonging to an object of the local class named B , contained in an object of class A , has direct access to private members of objects of the containing or enclosing class.

The private showA method will be called by a method named showB , belonging to an object of the local class B , to demonstrate the truth of this statement.

The method named delay

Listing 6 shows a utility method named delay , which is an instance method of class A .

The purpose of the delay method is simply to insert a 30-millisecond delay in the execution of the program. This method is used to cause certain activities in the execution of the program to be spread far enough apart in time to make them distinguishable, one from the other, on the basis of relative time.

The method named meth

The method named meth is an instance method of the class A . The beginning of this method is shown in Listing 7 .

The method named meth contains a local class definition for a class named B , which we will examine later.

As you can see in Listing 7 , it also declares a final local variable named methTime . As you will see later, the method named meth instantiates two separate objects of local class B and calls a method named showB on each of those objects.

The method named showB displays various data values that illustrate the characteristics of local classes, including the value of the final local variable named methTime .

Access to final local variables

One of the characteristics of a local class is that objects of a local class have access to local variables within the same scope, provided that those local variables are declared final .

Blank final variables

The code in Listing 7 declares a final local variable named methTime . Because of the syntax used, this variable is known as a blank final variable. A blank final variable is not initialized when it is declared.

As with all local variables, the variable cannot be used until a value has been assigned to it. Because this variable is declared final , once a value has been assigned to it, the value cannot be changed throughout the remaining life of the variable.

Set value of blank final variable

The code in Listing 8

  • Inserts a delay
  • Sets a value for the final local variable named methTime
  • Displays the value that was set in methTime
  • Inserts an additional delay before continuing

The value that is set in the variable named methTime is the relative time that the statement is executed.

The screen output

The code in the main method of Listing 1 calls meth on a new object of class A , producing the screen output shown in Image 3 .

(Once again, the actual time value displayed by your system may be different, depending on the speed of your system and other factors as well.)

The local class named B

The next block of code in the method named meth is the definition of a local class named B . The beginning of the class definition for local class B is shown in Listing 9 .

As with local variables, the class definition for a local class must appear before the code that attempts to instantiate the class. Code in the method named meth following the local class definition will instantiate and exercise objects of class B .

Local class B extends top-level class Y . This was done to illustrate that the inheritance hierarchy is independent of the containment hierarchy.

The constructor

The code in Listing 9 declares a private instance variable named bTime , which is used to store the relative time that an object of class B is constructed.

Listing 9 also shows the constructor for local class B , which establishes, saves, and then displays the relative time that that an object is instantiated.

(I will show you the screen output produced by this constructor shortly as I discuss code that instantiates objects of this class.)

Instantiate two objects of class B

At this point, I am going to temporarily set aside the discussion of local class B and discuss code in the method named meth that immediately follows the definition of local class B . This code is shown in Listing 10 .

Listing 10 shows the beginning of code that is called when the method named meth is called. This code begins by instantiating two objects from the class named B , with a delay inserted between the instantiation of the two objects.

The screen output

The code in Listing 10 , in conjunction with the constructor code in Listing 9 produces the screen output shown in Image 4 as each of the two objects of local class B are instantiated.

Call showB on the first object

Following this, the code in the method named meth calls the method named showB on each of the two objects. The method named showB will, in turn, call the method named showA on the containing object instantiated from the class named A . The third line of code in Listing 11 calls the method named showB on the first object instantiated in Listing 10 .

The method named showB

That brings us back to a discussion of the method named showB , which is an instance method of local class B . The beginning of the showB method is shown in Listing 12 . This method displays several private and protected variables, some of which belong to the containing object instantiated from the top-level class named A .

(Note that code in this method has direct access to xVar , which is a protected member variable of the superclass of the class named A .)

Items that are displayed

The code in Listing 12 displays

  • A visual line separator, -1-
  • A private instance variable, bTime , belonging to the object instantiated from local class B
  • A private instance variable, aTime , belonging to the containing object instantiated from the top-level class A
  • A final local variable, methTime , belonging to the method named meth , in which the local class B is defined
  • A protected instance variable, xVar , of the superclass of the class A , from which the containing object was instantiated.
  • A protected instance variable, yVar , of the superclass of the local class B
  • The name of the class file that represents the local class B

The screen output

The combined code in Listing 11 and Listing 12 produces the output shown in Image 5 for the first object instantiated from local class B .

Call private method showA

One of the important characteristics of local classes is that the methods of objects instantiated from local classes have direct access to all of the members, including private members, of all the containing classes in the containment hierarchy.

(In this case, an object of the local class B has only one containing class, an object instantiated from the top-level class A .)

Continuing with the method named showB , in local class B , the code in Listing 13 displays a line separator, -2-, and then calls the private method named showA on the containing object. This illustrates the containment hierarchy.

The screen output

The method named showA is shown in Listing 5 . The combination of the code in Listing 13 and Listing 5 produces the screen output shown in Image 6 .

Image 6 displays

  • The relative time that the containing object of the class A was instantiated
  • A protected instance variable in the superclass of the class from which the containing object was instantiated
  • The name of the class file that represents the top-level class named A

Use of the keyword this

As is the case with member classes, (discussed in the previous module), objects of local classes use a special syntax of the keyword this to gain access to objects in the containment hierarchy.

The code in Listing 14 shows how to use regular syntax to gain access to the current object, and how to use special syntax to gain access to the containing object.

Having gained access to the two objects, the code in Listing 14 gets and displays the values of private instance variables belonging to those objects.

The screen output

The code in Listing 14 produced the screen output shown in Image 7 .

You saw these same two values displayed earlier in Image 4 and Image 2 .

Illustrate the inheritance hierarchy

Remember that the inheritance hierarchy is independent of the containment hierarchy. The code in Listing 15 illustrates the inheritance hierarchy by

  • Calling the overridden toString method belonging to the local class B
  • Using the super keyword to call the overridden toString method belonging to the class Y , which is the superclass of the local class B

Listing 15 also defines the overridden toString method belonging to local class B . The overridden toString method belonging to class Y is shown in Listing 3 .

The screen output

The combined code in Listing 15 and Listing 3 produces the screen output shown in Image 8 . (Once again, you have seen these same values displayed in earlier Images.)

That concludes the results of calling the showB method on the first object instantiated from local class B .

Call showB method on second object

The code in Listing 10 instantiated two objects from local class B , and saved the object's references in instance variables named obj1 and obj2 . The screen output that I have been discussing resulted from calling the showB method on obj1 in Listing 11 .

Listing 16 calls the showB method on obj2 . Listing 16 also signals the end of the method named meth , and the end of the class named A .

The screen output The code in Listing 16 produces the screen output shown in Image 9

Important considerations The important things to note about the output shown in Listing 16 include:

  • The second object instantiated from local class B is definitely a different object from the first object instantiated from local class B , as evidenced by a different value for bTime . (Compare the value of bTime in Image 9 with the value of bTime in Image 5 .) In other words, the second object was instantiated after the first object was instantiated.
  • Even though the two objects instantiated from local class B are different objects, they both belong to the same containing object, as evidenced by the same values for aTime in Image 9 and Image 5 .
  • The two objects instantiated from local class B each access the same final local variable belonging to the method named meth , as evidenced by the same values for methTime in Image 9 and Image 5 .

Run the program

I encourage you to copy the code from Listing 17 . Compile the code and execute it. Experiment with the code, making changes, and observing the results of your changes. Make certain that you can explain why your changes behave as they do.

Summary

In addition to a number of other items, a class definition can contain:

  • Member classes
  • Local classes
  • Anonymous classes
  • Nested top-level classes and interfaces

Member classes were explained in the previous module. This module explains local classes. The next module will explain anonymous classes.

A local class is a class that is defined within a block of Java code. While local classes are probably most frequently defined within method and constructors, they can also be defined inside static initializer blocks and instance initializers.

An object of the local class must be internally linked to an object of the enclosing class (which I often refer to as the containing object). A local class is truly an inner class because an object of the local class cannot exist in the absence of an object of the enclosing class.

The methods of a local class have direct access to all the members in the hierarchy of enclosing classes, including private members. In addition, the methods of local classes have access to final local variables and final method parameters in the scope in which the local class is defined.

The containment hierarchy of local classes is independent of the inheritance hierarchy. However, it is technically possible to establish an inheritance relationship between a local class and one of its enclosing classes.

Local classes may not be declared public , protected , private , or static .

Local classes cannot contain static members.

A local class has approximately the same relationship to a member class that a local variable in a method has to an instance variable of the class containing the method.

What's next?

The next module in this series will explain and discuss anonymous classes, and will also compare anonymous classes to local classes.

Miscellaneous

This section contains a variety of miscellaneous information.

Note:

Housekeeping material
  • Module name: Java OOP: Local Classes
  • File: Java1638.htm
  • Published: 11/19/13
  • Revised: 11/20/13

Note:

Disclaimers:

Financial : Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

I also want you to know that, I receive no financial compensation from the Connexions website even if you purchase the PDF version of the module.

In the past, unknown individuals have copied my modules from cnx.org, converted them to Kindle books, and placed them for sale on Amazon.com showing me as the author. I neither receive compensation for those sales nor do I know who does receive compensation. If you purchase such a book, please be aware that it is a copy of a module that is freely available on cnx.org and that it was made and published without my prior knowledge.

Affiliation : I am a professor of Computer Information Technology at Austin Community College in Austin, TX.

Complete program listing

A complete listing of the program is provided in Listing 17 .

Images

Figure 1: Image 1: Class files produced by the program.
Image 1: Class files produced by the program.

A$1$B.class
A.class
InnerClasses07.class
X.class
Y.class
Figure 2: Image 2: Screen output.
Image 2: Screen output.
In xstr for A, aTime = 10
Figure 3: Image 3: Screen output.
Image 3: Screen output.
In meth, methTime = 40
Figure 4: Image 4: Screen output.
Image 4: Screen output.
----------------------
Instantiate first B-object
In xstr for B, bTime = 70
Delay and instantiate second B-object
In xstr for B, bTime = 100
Figure 5: Image 5: Screen output.
Image 5: Screen output.
----------------------
Display first B-Object
-1-
In showB, private bTime = 70
In showB, private aTime = 10
In showB, final methTime = 40
In showB, protected xVar = 1000
In showB, protected yVar = 2000
In showB, class name = A$1$B
Figure 6: Image 6: Screen output.
Image 6: Screen output.
-2-
In showA, aTime = 10
In showA, xVar = 1000
In showA, class name = A
Figure 7: Image 7: Screen output.
Image 7: Screen output.
-3-
In showB, bTime = 70
In showB, aTime = 10
Figure 8: Image 8: Screen output.
Image 8: Screen output.
-4-
toString in class B, bTime = 70
toString in class Y, yVar = 2000
Figure 9: Image 9: Screen output.
Image 9: Screen output.
----------------------
Display second B-Object
-1-
In showB, private bTime = 100
In showB, private aTime = 10
In showB, final methTime = 40
In showB, protected xVar = 1000
In showB, protected yVar = 2000
In showB, class name = A$1$B
-2-
In showA, aTime = 10
In showA, xVar = 1000
In showA, class name = A
-3-
In showB, bTime = 100
In showB, aTime = 10
-4-
toString in class B, bTime = 100
toString in class Y, yVar = 2000

Listings

Listing 1: The controlling class named InnerClasses07.

public class InnerClasses07{

  static long baseTime = new Date().getTime();

  public static void main(String[] args){
    new A().meth();
  }//end main
}//end class InnerClasses07

Listing 2: The class named X.

class X{
  protected int xVar = 1000;
}//end class X

Listing 3: The class named Y.

class Y{
  protected int yVar = 2000;

  public String toString(){
    return "toString in class Y, yVar = " + yVar;
  }//end overridden toString
}//end class Y

Listing 4: Beginning of the class named A.

class A extends X{
  private long aTime = new Date().getTime() -
                         InnerClasses07.baseTime;

  A(){//constructor
    System.out.println(
              "In xstr for A, aTime = " + aTime);
  }//end constructor

Listing 5: The showA method in class A.

  private void showA(){
    System.out.println(
                   "In showA, aTime = " + aTime);
    System.out.println(
                     "In showA, xVar = " + xVar);
    System.out.println("In showA, class name = "
                         + getClass().getName());
  }//end showA

Listing 6: The delay method in class A.

  void delay(){
    try{
      Thread.currentThread().sleep(30);
    }catch(InterruptedException e){
      System.out.println(e);
    }//end catch
  }//end delay

Listing 7: Beginning the meth method in class A.

  void meth(){
    final long methTime;

Listing 8: Set value of blank final variable.

    delay();
    methTime = new Date().getTime() -
                         InnerClasses07.baseTime;
    System.out.println(
              "In meth, methTime = " + methTime);
    delay();

Listing 9: Beginning of class definition for local class B.

    class B extends Y{
      private long bTime;

      B(){//constructor
        bTime = new Date().getTime() -
                         InnerClasses07.baseTime;
        System.out.println(
              "In xstr for B, bTime = " + bTime);
      }//end constructor

Listing 10: Instantiate two objects of local class B.

    System.out.println("----------------------");
    System.out.println(
                   "Instantiate first B-object");
    final B obj1 = new B();
    System.out.println(
        "Delay and instantiate second B-object");
    delay();
    final B obj2 = new B();

Listing 11: Call showB on the first object.

    System.out.println("----------------------");
    System.out.println("Display first B-Object");
    obj1.showB()

Listing 12: Beginning of showB method in local class B.

//Continuing with local class B definition
      void showB(){
        System.out.println("-1-");
        System.out.println(
           "In showB, private bTime = " + bTime);
        System.out.println(
           "In showB, private aTime = " + aTime);
        System.out.println(
                  "In showB, final methTime = " +
                                       methTime);
        System.out.println(
           "In showB, protected xVar = " + xVar);
        System.out.println(
           "In showB, protected yVar = " + yVar);
        System.out.println(
                      "In showB, class name = " +
                           getClass().getName());

Listing 13: More code from showB method.

        System.out.println("-2-");
        showA();

Listing 14: Use of the keyword this.

        System.out.println("-3-");
        System.out.println(
              "In showB, bTime = " + this.bTime);
        System.out.println(
            "In showB, aTime = " + A.this.aTime)

Listing 15: Illustrate the inheritance hierarchy.

        System.out.println("-4-");
        System.out.println(toString());
        System.out.println(super.toString());
      }//end showB
      //---------------------------------------//

      //Overridden toString method
      public String toString(){
        return
         "toString in class B, bTime = " + bTime;
      }//end overridden toString
    }//end local class B

Listing 16: Call showB method on second object.

    System.out.println("----------------------");
    System.out.println(
                      "Display second B-Object");
    obj2.showB();

  }// end meth
}//end class A

Listing 17: Complete program listing.

/*File InnerClasses07.java
Copyright 2003 R.G.Baldwin

Illustrates the use of local classes.

This program defines a local class named B inside
an instance method named meth.  The method named
meth is an instance method of a class named A.

The method named meth instantiates two separate
objects of the local class named B, and calls
on each of them a method named showB, which
displays certain data values that illustrate the
characteristics of local classes, a well as the
relationships among objects of a local class and
an object to which that object is internally
associated.  In this case, objects of the class
named B are internally associated with an object
of the class named A.

This program produces the following class files
when compiled:

A$1$B.class
A.class
InnerClasses07.class
X.class
Y.class

The file named A$1$B.class represents the local
class named B.

This program produces the following output:

In xstr for A, aTime = 10
In meth, methTime = 40
----------------------
Instantiate first B-object
In xstr for B, bTime = 70
Delay and instantiate second B-object
In xstr for B, bTime = 100
----------------------
Display first B-Object
-1-
In showB, private bTime = 70
In showB, private aTime = 10
In showB, final methTime = 40
In showB, protected xVar = 1000
In showB, protected yVar = 2000
In showB, class name = A$1$B
-2-
In showA, aTime = 10
In showA, xVar = 1000
In showA, class name = A
-3-
In showB, bTime = 70
In showB, aTime = 10
-4-
toString in class B, bTime = 70
toString in class Y, yVar = 2000
----------------------
Display second B-Object
-1-
In showB, private bTime = 100
In showB, private aTime = 10
In showB, final methTime = 40
In showB, protected xVar = 1000
In showB, protected yVar = 2000
In showB, class name = A$1$B
-2-
In showA, aTime = 10
In showA, xVar = 1000
In showA, class name = A
-3-
In showB, bTime = 100
In showB, aTime = 10
-4-
toString in class B, bTime = 100
toString in class Y, yVar = 2000


Tested using SDK 1.4.1 under WinXP
************************************************/
import java.util.Date;

public class InnerClasses07{
  //The following static variable is used as a
  // base to establish the relative points in
  // time that certain activities occur during
  // the execution of the program.
  static long baseTime = new Date().getTime();

  public static void main(String[] args){
    //Instantiate a new object of the class named
    // A and call the method named meth on that
    // object.  This method will sequentially
    // instantiate two separate objects of a
    // local class named B that is defined inside
    // the method named meth.  Then it will
    // call a method named showB on each of
    // those objects to cause them to display
    // various data values that illustrate the
    // characteristics of local classes.
    new A().meth();
  }//end main
}//end class InnerClasses07
//=============================================//

//The class named A extends this class to
// illustrate the difference between the
// inheritance hierarchy and the containment
// hierarchy.
class X{
  protected int xVar = 1000;
}//end class X
//=============================================//

//The local class named B extends this class to
// illustrate the difference between the
// inheritance hierarchy and the containment
// hierarchy.
class Y{
  protected int yVar = 2000;

  //Overridden toString method
  public String toString(){
    return "toString in class Y, yVar = " + yVar;
  }//end overridden toString
}//end class Y
//=============================================//

class A extends X{
  //Establish the relative time that the object
  // of class A is instantiated.
  private long aTime = new Date().getTime() -
                         InnerClasses07.baseTime;

  A(){//constructor
    System.out.println(
              "In xstr for A, aTime = " + aTime);
  }//end constructor
  //-------------------------------------------//

  //Displays information about the object
  // instantiated from class A.
  private void showA(){
    System.out.println(
                   "In showA, aTime = " + aTime);
    System.out.println(
                     "In showA, xVar = " + xVar);
    System.out.println("In showA, class name = "
                         + getClass().getName());
  }//end showA
  //-------------------------------------------//

  //Method used to insert a time delay of 30
  // milliseconds.
  void delay(){
    try{
      Thread.currentThread().sleep(30);
    }catch(InterruptedException e){
      System.out.println(e);
    }//end catch
  }//end delay
  //-------------------------------------------//

  //This method contains a local class definition
  // for a class named B.  The method
  // instantiates two separate objects of class B
  // and calls a method named showB on each of
  // the objects.  The method named showB
  // displays various data values that illustrate
  // the characteristics of local classes.
  void meth(){
    //The following local variable must be final
    // to be accessible from a local class.  This
    // is a blank final variable whose value can
    // be set once and never changed after that.
    final long methTime;

    //Delay and then set the value of the blank
    // final local variable to a relative time.
    // Then delay again before continuing.
    delay();
    methTime = new Date().getTime() -
                         InnerClasses07.baseTime;
    System.out.println(
              "In meth, methTime = " + methTime);
    delay();
  //-------------------------------------------//

    //This is the definition of a local class
    // named B.  Note that as with local
    // variables, the class definition must
    // appear before the code that attempts to
    // instantiate the class.  The class extends
    // class Y to illustrate that the inheritance
    // hierarchy is independent of the
    // containment hierarchy.
    class B extends Y{
      private long bTime;

      B(){//constructor
        //Establish the relative time that the
        // object is instantiated.
        bTime = new Date().getTime() -
                         InnerClasses07.baseTime;
        System.out.println(
              "In xstr for B, bTime = " + bTime);
      }//end constructor

      void showB(){
        //Display private and protected
        // variables, some of which belong to the
        // internally associated object
        // instantiated from the class named A.
        // Note that code in this method has
        // access to xVar, which is a protected
        // member variable of a superclass of the
        // class named A.
        System.out.println("-1-");
        System.out.println(
           "In showB, private bTime = " + bTime);
        System.out.println(
           "In showB, private aTime = " + aTime);
        System.out.println(
                  "In showB, final methTime = " +
                                       methTime);
        System.out.println(
           "In showB, protected xVar = " + xVar);
        System.out.println(
           "In showB, protected yVar = " + yVar);
        System.out.println(
                      "In showB, class name = " +
                           getClass().getName());

        System.out.println("-2-");
        //Call the private method named showA
        // in the internally associated object
        // instantiated from the class named A,
        // to illustrate the containment
        // hierarchy.
        showA();

        System.out.println("-3-");
        //Show how to access individual objects,
        // including the internally associated
        // object instantiated from the class
        // named A.
        System.out.println(
              "In showB, bTime = " + this.bTime);
        System.out.println(
            "In showB, aTime = " + A.this.aTime);

        System.out.println("-4-");
        //Illustrate the inheritance hierarchy by
        // calling the overridden toString
        // methods belonging to the class named B
        // and its superclass named Y.
        System.out.println(toString());
        System.out.println(super.toString());
      }//end showB
      //---------------------------------------//

      //Overridden toString method
      public String toString(){
        return
         "toString in class B, bTime = " + bTime;
      }//end overridden toString
    }//end local class B

    //This is the code that is executed when this
    // method named meth is called.  Instantiate
    // two objects from the class named B and
    // call the method named showB on each of
    // them.  Those methods will, in turn call
    // the method named showA on the internally
    // associated object instantiated from the
    // class named A.  Insert a delay between the
    // instantiation of the two objects.
    System.out.println("----------------------");
    System.out.println(
                   "Instantiate first B-object");
    final B obj1 = new B();
    System.out.println(
        "Delay and instantiate second B-object");
    delay();
    final B obj2 = new B();

    System.out.println("----------------------");
    System.out.println("Display first B-Object");
    obj1.showB();
    System.out.println("----------------------");
    System.out.println(
                      "Display second B-Object");
    obj2.showB();

  }// end meth
}//end class A
//=============================================//

-end-

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks