Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
To help you get a handle on inner classes and what they are good for, let's revisit theStack
class. Suppose that you want to add to this class a feature that lets another class enumerate the elements in the stack, using thejava.util.Iterator
interface. This interface contains three method declarations:public boolean hasNext(); public <E> 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()) { E element = next(); //do something with element }The
Note: TheIterator
interface and theArrayList
class use generic types. To be as general as possible, this example is parameterized withObject
. If generics are unfamiliar to you, see GenericsStack
class itself should not implement theIterator
interface, because of certain limitations imposed by the API of theIterator
interface: two separate objects could not enumerate the items in theStack
concurrently, because there's no way of knowing who's calling the next method; the enumeration could not be restarted, because theIterator
interface doesn't have methods to support that; and the enumeration could be invoked only once, because theIterator
interface doesn't have methods for going back to the beginning. Instead, a helper class should do the work forStack
.The helper class must have access to the
Stack
's elements and also must be able to access them directly because theStack
's public interface supports only LIFO access. This is where inner classes come in.Here's a
Stack
implementation that defines a helper class, calledStackIterator
, for enumerating the stack's elements:Note that thepublic class Stack { private ArrayList<Object> items; //code for Stack's methods and constructors //not shown public Iterator<Object> iterator() { return new StackIterator(); } private class StackIterator implements Iterator { int currentItem = items.size() - 1; public boolean hasNext() { ... } public ArrayList<Object> next() { ... } public void remove() { ... } } }StackIterator
class refers directly toStack
'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:An anonymous class is generally used inside an expression and it does not have member scope, since it isn't visible to the enclosing class. 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.public class Stack { private ArrayList<Object> items; //code for Stack's methods and constructors //not shown public Iterator<Object> iterator() { return new Iterator<Object>() { int currentItem = items.size() - 1; public boolean hasNext() { ... } public ArrayList<Object> next() { ... } public void remove() { ... } }; } }If you want to use an anonymous inner class, but it's too long to include inline, you can use a local class. A local class is like a named anonymous class. Typically, a local class is declared within a method or to initialize a field and, like an anonymous class, it also does not have member scope. For example, using the
Stack
example, theStackIterator
class could be implemented as a local class inside theiterator
method, like this:public class Stack { private ArrayList<Object> items; //code for Stack's methods and constructors //not shown public Iterator<Object> iterator() { private class StackIterator implements Iterator<Object> { int currentItem = items.size() - 1; public boolean hasNext() { ... } public ArrayList<Object> next() { ... } public void remove() { ... } } return new StackIterator(); } }
Like other classes, nested classes can be declaredabstract
orfinal
. 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
, andprotected
to restrict access to nested classes, just as you do to other class members.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.