The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Learning the Java Language
Lesson: Classes and Inheritance

Inner Classes

To help you get a handle on inner classes and what they are good for, let's revisit the Stack class. Suppose that you want to add to this class a feature that lets another class enumerate the elements in the stack, using the java.util.Iterator interface. This interface contains three method declarations:
public boolean hasNext();
public Object next();
public void remove();
Iterator defines the interface for stepping once through the elements within an ordered set in order. You use it like this:
while (hasNext()) {
    next();
}
The Stack class itself should not implement the Iterator interface, because of certain limitations imposed by the API of the Iterator interface: two separate objects could not enumerate the items in the Stack concurrently, because there's no way of knowing who's calling the next method; the enumeration could not be restarted, because the Iterator interface doesn't have methods to support that; and the enumeration could be invoked only once, because the Iterator interface doesn't have methods for going back to the beginning. Instead, a helper class should do the work for Stack.

The helper class must have access to the Stack's elements and also must be able to access them directly because the Stack's public interface supports only LIFO access. This is where inner classes come in.

Here's a Stack implementation that defines a helper class, called StackIterator, for enumerating the stack's elements:

public class Stack {
    private Object[] items;

    //code for Stack's methods and constructors
    not shown

    public Iterator iterator() {
        return new StackIterator();
    }
    class StackIterator implements Iterator {
        int currentItem = items.size() - 1;

        public boolean hasNext() {
            ...
        }
        public Object next() {
            ...
        }
        public void remove() {
            ...
        }
    }
}
Note that the StackIterator class refers directly to Stack's items instance variable.

Inner classes are used primarily to implement helper classes like the one shown in this example. If you plan on handling user-interface events, you'll need to know about using inner classes because the event-handling mechanism makes extensive use of them.

You can declare an inner class without naming it, called an anonymous class. Here's yet another version of the Stack class, in this case using an anonymous class for its iterator:

public class Stack {
    private Object[] items;

    //code for Stack's methods and constructors
    not shown

    public Iterator iterator() {
        return new Iterator() {
            int currentItem = items.size() - 1;
            public boolean hasNext() {
                ...
            }
            public Object next() {
                ...
            }
            public void remove() {
                ...
            }
        }
    }
}
Anonymous classes can make code difficult to read. You should limit their use to those classes that are very small (no more than a method or two) and whose use is well understood, such as event-handling classes.

Other Facts about Nested Classes

Like other classes, nested classes can be declared abstract or final. The meaning of these two modifiers for nested classes is the same as for other classes. Also, you may use the access specifiers — private, public, and protected — to restrict access to nested classes, just as you do to other class members.

Any nested class, not just anonymous ones, can be declared in any block of code. A nested class declared within a method or other smaller block of code has access to any final or local variables in scope.


Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.