A nested class is a class defined within another class. A nested class should exist
only to serve its enclosing class. If a nested class would be useful in some
other context, then it should be a top-level class. There are four kinds of
nested classes: static member classes, nonstatic member classes, anonymous classes, and local classes. All but the first kind are known as inner classes. This item tells you when to use which kind of nested class and
why.
A static
member class is the simplest kind of nested class. It is best thought of as an
ordinary class that happens to be declared inside another class and has access
to all of the enclosing class’s members, even those declared private. A static
member class is a static member of its enclosing class and obeys the same
accessibility rules as other static members. If it is declared private, it is
accessible only within the enclosing class, and so forth.
Syntactically,
the only difference between static and nonstatic member classes is that static
member classes have the modifier static
in
their declarations. Despite the syntactic similarity, these two kinds of nested
classes are very different. Each instance of a nonstatic member class is
implicitly associated with an enclosing
instance of
its containing class.
One common use
of a nonstatic member class is to define an Adapter that allows
an instance of the outer class to be viewed as an instance of some unrelated
class. For example, implementations of the Map
interface
typically use nonstatic member classes to implement their collection views, which are returned by Map’s keySet, entrySet, and values methods.
// Typical use of a nonstatic member class
public class MySet<E> extends AbstractSet<E>
{
... // Bulk of the class omitted
public Iterator<E> iterator() {
return new MyIterator();
}
private class MyIterator implements
Iterator<E> {
...
}
}
If you declare a
member class that does not require access to an enclosing instance, always put the static
modifier
in its declaration, making it a static rather than a nonstatic member class.
Anonymous
classes are unlike anything else in the Java programming language. As you would
expect, an anonymous class has no name. It is not a member of its enclosing
class. Rather than being declared along with other members, it is
simultaneously declared and instantiated at the point of use. Anonymous classes
are permitted at any point in the code where an expression is legal. Anonymous
classes have enclosing instances if and only if they occur in a nonstatic
context. But even if they occur in a static context, they cannot have any
static members.
There are many
limitations on the applicability of anonymous classes. You can’t instantiate
them except at the point they’re declared. You can’t perform instanceof tests or do anything else that requires you
to name the class. You can’t declare an anonymous class to implement multiple
interfaces, or to extend a class and implement an interface at the same time.
Clients of an anonymous class can’t invoke any members except those it inherits
from its supertype. Because
anonymous
classes occur in the midst of expressions, they must be kept short— about ten
lines or fewer—or readability will suffer.
One common use
of anonymous classes is to create function objects (Item 21) on
the fly. For example, the sort method invocation on sorts an
array of strings according to their length using an anonymous Comparator instance. Another common use of anonymous
classes is to create process objects, such as Runnable, Thread, or TimerTask instances. A third common use is within
static factory methods (see the intArrayAsList
method
in Item 18).
Local classes
are the least frequently used of the four kinds of nested classes. A local
class can be declared anywhere a local variable can be declared and obeys the
same scoping rules. Local classes have attributes in common with each of the
other kinds of nested classes. Like member classes, they have names and can be
used repeatedly. Like anonymous classes, they have enclosing instances only if
they are defined in a nonstatic context, and they cannot contain static
members. And like anonymous classes, they should be kept short so as not to
harm readability.
Reference: Effective Java 2nd Edition by Joshua Bloch