Nested Classes, Part 3

Editor's note: Robert Simmons concludes his quest to clarify the uses, advantages, and pitfalls to using Java's various nested classes with this week's third installment on the subject, excerpted from his book Hardcore Java. Robert covers static nested classes and how they differ from inner classes; double nested classes and whether and when to use them; and nested classes and interfaces and their usefulness, or lack thereof. (If you missed either of the first two installments in this series, you'll find links to those excerpts on these pages as well.)

Static Nested Classes

A static nested class is, not surprisingly,a nested class that is declared with the keyword
static on the declaration. Many developers call these classes "inner classes" as
well. However, these developers are wrong. To be an inner class, a class has to have
instance scope. To understand how static nested classes function, see Example 6-8.

This code declares a public static nested class. This nested class can access the various
static members of the enclosing class. However, unlike inner classes, it cannot
access any instance variables in the enclosing class. This is an important difference
between static nested classes and inner classes. Formally, it can be said that an inner
class is instance-scoped and a static nested class is class-scoped. The class scope of a
static nested class makes it easier to use:

With this import syntax,the class is quite easy to use. However,static nested classes
can also use access specifiers. You can have public, private, protected, package, final, and even abstract static nested classes. If you try to access a static nested class outside of its visibility, your code won't compile, as the following snippet demonstrates:

Private and protected static nested classes have predictable visibility and specialized
functions. Generally,they are used to implement internal features of a class or class
hierarchy. For example,the Java collection classes use private static nested classes to
implement the entries in their data structures. (For an example,see the source code
to java.util.HashTable.) On the other hand,public static nested classes are often
used to group classes together or give a group of classes access to private static
resources.

When using static nested classes,your first concern should be whether package
scope is sufficient for your class. If it isn't,then by all means use static nested classes.
If package scope will suffice,then it is better,for the sake of readability,to declare
the class normally.

Of all the nested classes,static nested classes are the easiest to use,read,and understand.
Unless you positively need to access the instance variables of a class,I recommend
you make your nested classes static whenever possible.

Double Nested Classes

One peculiar form of declaration that I came across while working for an aerospace
company was a nested class within a nested class. The dynamics of this sort of declaration
are similar to those of a normal nested class. The difference is that the dynamics
extend to the subnested class as well as the nested class. See Example 6-9.

In this example,the class SomeOtherClass is nested inside of the class SomeClass.
Because of the double nesting, SomeOtherClass can access the private final static
members of DoubleNestedClass as well as those of SomeClass. The dynamics extend
down the nesting. Similar rules apply to method-scoped and instance-scoped double
nested classes. For example, a method-scoped double nested class would have access
to instance variables and final local variables of the declaring method. Regardless of
how deep the nesting is, the rules propagate down.

However, just because you can use double nested classes doesn't necessarily mean
you should. In fact, I can't think of a single legitimate reason for double nested
classes. If you find yourself writing one of these, you should probably rethink your
architecture. If you find yourself doing this routinely, you may want to consider taking
a long vacation.

Nested Classes in Interfaces?

Java supports the concept of nested classes in interfaces. The syntax and dynamics
work just like nested classes declared in a class. However, declaring a class nested
inside an interface would be extremely bad programming. An interface is an abstraction
of a concept, not an implementation of one. Therefore, implementation details
should be left out of interfaces. Remember, just because you can cut off your hand
with a saw doesn't mean that it's a particularly good idea.

Nested Interfaces

As with classes, you can nest interfaces inside an outer class or another interface. The
dynamics are similar to nested classes. However, keep in mind that the classes that
ultimately implement these nested interfaces don't have the special access to the
class members that a nested class does; instead,they behave just like normally
declared classes.

Nested Interfaces in Classes

The syntax for nested interfaces is the same as nested classes, but the results are
quite different. Since you are defining only the interface and not the implementation,
the user of the interface is free to implement the class any way he wants. A good
example of a nested interface implementation is with a special collection. See
Example 6-10.

In this example, the special collection named Inventory will contain only objects that
implement the InventoryItem interface (and therefore define the method getSKU( )).
Furthermore, since you don't want to tie down the inventory items to a particular
superclass, you make an interface for the inventory items, which allows the user to
implement that interface as he sees fit.

There are only a few good reasons why you should use inner interfaces. One is to
model a composition relationship without restricting the implementation of the composed
object. In this case, you would need an inner interface to model the compositional
relationship and to let the user of the interface decide on the implementation.

Nested interfaces are useful on rare occasions, but most of the time you can achieve
the same results simply by declaring the interface in its own file.

Nested Interfaces in Interfaces

It is also possible to nest interfaces within other interfaces, although this is rarely
done. The syntax is the same as with nested classes. Although using interfaces nested
in other interfaces is less crazy than nesting classes within an interface, it is still
pretty weird.

Essentially, when you nest an interface inside another interface, you are describing a
compositional relationship among interfaces. Conceptually, it is a rather strange
thing to do. Therefore, I don't recommend nesting interfaces.

Ultimately, nesting classes or interfaces inside other interfaces should probably be
blocked by the compiler because using them makes no sense in object-oriented programming.
All you can hope to accomplish is to demonstrate some obscure aspects
of Java for the admiration of your junior developers. Its practical usefulness is about
zero.

Nested Class Rules

Nested classes have many confusing rules. Table 6-1 will help you keep them
straight.

Table 6-1. Nested class references

Type

Scope

Access

Keywords

method

instance

class

method final

class final

class static

instance

abstract/final

private

protected

public

Anonymous

*

*

*

*

*

Limited-scope

*

*

*

*

*

*

Inner

*

*

*

*

*

*

*

*

Static nested

*

*

*

*

*

*

*

Although most of the nested classes in this chapter are not recommended for routine
use, it is important that you understand their dynamics. You may come across these
nested class types down the line,and knowing how they work could save you time
and frustration.

Although many developers tend to overuse nested classes, they can be a valuable
asset to your development process. When it comes to modeling composition relationships
and implementing internals of a class that you want to hide, they can't be
beat.

Robert Simmons, Jr.
lives and works as a senior software architect in Germany. He is the author of O'Reilly's Hardcore Java.