Section 9.1. Inner Classes

   

9.1 Inner Classes

Inner classes are an advanced topic. They are not totally intuitive. Nor are they regularly necessary if you're mostly writing Java for the Web. The primary use of inner classes is in GUI development. They are covered here in the interest of completeness and flexibility.

Inner classes are also sometimes called nested classes. Simply put, an inner class is a class that has its definition inside of another class. Inner classes have complete access to the code in the outer class definition, including its private fields and methods .

When you compile a source file containing a class with an inner class definition, two .class files are created.

Note

There is an interesting thing about compilation and organization that comes up when you start working with inner classes. Only public Java classes need to go into separate files. You can therefore define many different classes inside one source file.


What do inner classes do for you? In a sense, they allow you to scope your classes, because the inner class becomes a member of the outer class. That is, the inner class acts as a property of the outer class just like its regular fields or methods.

Objects in an inner class have access to even the private variables in instances of the outer class. Typically, inner classes are useful when you want to define helpers ”that is, classes that have a very specific purpose and require another class (the outer class) to be employed. The most common place for these is in GUI development. For instance, to create a useful window with menus and buttons in Java, you need to create listeners that handle events (such as a mouse press, a button click, etc.). These items are often handled in inner classes, as registering a mouse drag must have somewhere (like a panel that is listening for the drag) to be registered so you can do something like draw a line.

There are four kinds of inner classes:

  • Regular inner classes

  • Method-local inner classes

  • Anonymous inner classes

  • Top-level nested classes

We will look at these in turn now.

9.1.1 Regular Inner Classes

A regular inner class is defined inside another class, like this:

 class AnOuterClass {   class AnInnerClass {} } 

In order to instantiate an inner class, you must first have an instance of the outer class. You cannot instantiate an object of an inner class without first having an object of the outer class. Generally, an object of the inner class is created by the outer class. One advantage to using inner classes is that they can be hidden from other classes in the same package. A class can define more than one inner class.

Another chief reason to use inner classes is that each inner class can inherit an implementation independently. This is, in a way, the answer to the fact that Java classes cannot allow multiple inheritance as C++ allows.

Note

An inner class method can access data in its own fields and data fields in objects of the outer class that created it.


Inner classes, unlike regular classes, can be declared private . When you construct objects of the inner class, these objects are not instance fields of the outer class ”they are local to methods of the outer class.

The obvious benefit of inner classes is that they support encapsulation. Because only the outer class can call the inner class, you can go an extra step toward locking down access to your objects.

Objects of an inner class exist relative to objects of the outer class. Creating an object of the inner class from a non-static method of the outer class is relatively straightforward:

 AnInnerClass ic = new AnInnerClass(); 

If you are in a static method of the outer class, you don't have an implicit reference to an object (no this ). If you are in another class altogether, you don't have an object to work with either. You can still create an inner class instance in these cases, but you have to do it differently:

 public class InnerClassTest {   public static void main(String[] arg) {      OuterClass oc = new OuterClass();      // use this instance to create inner class instance      OuterClass.InnerClass in = oc.new InnerClass()   } } 

Here is an example of using an inner class. This file allows you to make a string. It then converts the string into a char array, loops over the char array, and finds the letters closest to the beginning and end of the alphabet.

9.1.2 OuterClassTest.java

 // demonstrate using an inner class  class OuterClass {             // declare a char array to hold letters             // that make up the string we pass in         char letters[];             // constructor OuterClass(String s) { letters =  s.toCharArray(); }             // a method of the outer class void getValues() {             // instantiate inner class InnerClass innerObject = new InnerClass();                 char lowest = innerObject.lowestChar();                 char highest = innerObject.highestChar();      System.out.println("Lowest letter: " + lowest);      System.out.println("Highest letter: " + highest); }             // here's the inner class             // whose job it is to do the real work class InnerClass {                     // loop through char array to find                     // the character closest to beginning of                     // alphabet      char lowestChar() {           char x = letters[0];                for(char i = 0; i < letters.length; i++)                     if (letters[i] < x)                          x = letters[i];                     return x;       }                     // loop through char array to find                     // letter in the string closest to the END                     // of the alphabet       char highestChar() {           char x = letters[0];                for(char i = 0; i < letters.length; i++)                     if (letters[i] > x) x = letters[i];                     return x;       }    } } class OuterClassTest {      public static void main(String[] ar) {                     // create a string                     // we will find the lowest and                     // highest letters in it                     // note that capital letters come first.                     // that is, C is 'lower' than c.            String s = "CFMX";                     // pass string to the outer class object            OuterClass outerObject = new OuterClass(s);                     // call the getValues method                     // defined in the outer class                     // even though its implementation is                     // defined in the inner class            outerObject.getValues();       } } // eof 

The output is like this:

 Lowest letter: C  Highest letter: X 

9.1.3 Method-Local Inner Classes

The second type of inner class is a method-local inner class. As the name suggests, it gives you a way to define an inner class inside a method:

 class AnOuterClass { void someMethod() { class AnInnerClass { // inner class definition here } // end inner class definition // instantiate inner class. This must come after the code that // defines the inner class AnInnerClass mi = new AnInnerClass(); } // end someMethod } // end outer class 

The primary difference between a regular inner class and a method-local inner class is that the inner object defined method-local cannot use the local variables of the method that contains the inner class definition. Only in the event that local variables or arguments are declared final can an object of an inner class have access to them.

9.1.4 Anonymous Inner Classes

The final place that you will see inner classes defined is perhaps surprising: inside a method invocation argument. Because anonymous inner classes are defined inside a method, all restrictions apply to them that apply to method-local inner classes.

Note

As with regular inner classes, when you compile a source file containing a class with an anonymous inner class definition, a separate class file is created for it.


Anonymous inner classes are declared and instantiated at the same time. They are instantiated using the new operator in conjunction with the name of a class or interface that already exists. The most common place to see the use of anonymous inner classes is in the code for Swing GUI controls. The aim is to keep the code that handles an action in the same place where you create a control. Creating an anonymous inner class looks like this:

 button.addActionListener(new ActionListener() {    public void actionPerformed(ActionEvent e) {          showStatus("button pushed");          }     } // end anonymous inner class ); // end the addActionListener method call 

The addActionListener() method takes only one argument ”one of type ActionListener . So our argument to the method is a single generated instance of an anonymous inner class.

Here is a complete example of anonymous inner classes in use:

9.1.5 AnonymousTest.java

 // show use of anonymous inner classes  import java.applet.*; import java.awt.*; import java.awt.event.*; public class AnonymousTest extends Applet {      // declare a button Button myB;      // initialize applet public void init() {      // create a new button an add      // to pane add(myB = new Button("Push Me"));      // we need to explicitly declare our      // interest in things that happen to the      // button. We do this by adding an action      // listener to the button myB.addActionListener(new ActionListener() {      public void actionPerformed(ActionEvent evt) {           showStatus("I needed that!");           }       }); // end addActionListener arg list   } // end init } // eof 

Note

In an applet, the init() method is called after the applet instance is initially created by the browser.


To test this, create a simple HTML page that calls the applet, like this:

9.1.6 ShowAnonymousTest.html

 <html>  <head> <title>Anonymoous Test</title> </head> <body> <applet align="center" code="AnonymousTest.class" width="200" height="200"></applet> </body> </html> 

You can call the applet using the appletviewer utility that comes with the JDK. At the command line, type something like this:

 C:\>appletviewer  CFusionMX\wwwroot\chp9\ShowAnonymousTest.html 

Note

We cover applets in some detail in Chapter 10. If you're having difficulty calling the applet, consult that chapter.


9.1.7 Top-Level Nested Classes

A top-level nested class is a class defined within another. The difference between these and inner classes is that a top-level nested class can be instantiated without an instance of the outer class. The top-level nested class is defined just like a regular inner class, but it is modified with the keyword static .

The reason to create a top-level nested class instead of a regular Java class is that it allows you to force the nested class to belong to the outer class nominally without it being a true member of the outer class. That is, once you have created an instance of the top-level nested class, it has no other relationship to any outer class instances.

A top-level nested class can be instantiated provided you have access to the outer class without requiring outer instance references. You create a top-level nested inner class like so:

 public class AnOuterClass {   public static class AnInnerClass { } } 

Call it like this:

 AnInnerClass in = new AnOuterClass.TheInner(); 

In general, it is best to use named top-level classes when your class definition is more than a few lines long.


     
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net