Concepts / Static Nested Classes

Static Nested Classes

Compiling a class with a nested class creates two separate class files.

  • Programming

Why Place One Class Inside Another

Most Java classes you have written so far probably sit at the top level of a file, each one standing on its own. Java also allows a class to be declared inside the body of another class. When that happens, the inner class is called a nested class. This article focuses on one particular kind of nested class: the static nested class, which carries the static modifier in its declaration.

The usual reason for placing one class inside another is organization. A helper type that only makes sense in the context of a larger type can be kept right next to that larger type, so the code describing one concept lives together. Placement also changes how the inner class is named, referred to, and used, and those changes are the main subject of this article.

What do you think happens?

You write one class and place another class inside its body, then compile the single source file. How many class files do you expect to find in the build output?

  • One, because the nested class sits inside the outer class's source code

  • Two, one for the outer class and one for the nested class

  • Three or more, one for every method

Reveal answer
Answer:

Two class files: one for the outer class and one for the nested class.

The nested class sits physically inside the outer class's source, so it is tempting to assume its compiled form is tucked inside the outer class's output. It is not. The compiler produces a separate class file for the nested class. Nothing in the code asks for two files; the compiler handles this automatically.

What the Compiler Writes to Disk

Follow one source definition through the compiler. The source file defines an outer class called WireFrameModel, and inside its body it declares a static nested class called Line. You give the compiler one source definition. The compiler produces two class files, and the outer class's own file is one of them. The other is the file for the nested class.

WireFrameModelsourceone source definitionWireFrameModel.classouter class fileWireFrameModel$Line.classnested class filecompiles tocompiles to
When one source file defines an outer class and a nested class, which class files appear on disk, and how do their names relate to each other?

The nested class's file is named WireFrameModel$Line.class. The name combines three pieces: the outer class name, a dollar sign, and the nested class name. That combined name ties the file back to the class that contains it. When you inspect a build folder later, look for the $-separated name to find a nested class.

Key point

A single source definition that contains a nested class produces two separate class files. The nested class is stored in its own file, not inside the outer class's file. Expect one class file per class when you inspect compiled output.

Declaring a Static Nested Class

Definition

A static nested class is a class declared inside another class with the static modifier, and it is part of the static structure of its containing class. The class that contains it is called the outer class or the containing class.

The declaration of a static nested class looks almost identical to the declaration of any other class. Two things are added. The class is written inside the body of another class, and the keyword static appears as part of its declaration. Nothing else about how the class is written needs to change.

The source's running example is a WireFrameModel. A wireframe model is a set of lines in three-dimensional space, the kind of model used to represent three-dimensional objects in graphics programs. The WireFrameModel class holds other members and also contains a static nested class named Line. That Line class represents one line, stored as two endpoints: one with coordinates x1, y1, z1 and the other with coordinates x2, y2, z2. Here the outer class is WireFrameModel and the nested class is Line.

java
Output
Dune
Notes on the code
  • Bookshelf is the outer (containing) class
  • static class Book is the static nested class, declared inside Bookshelf's body
  • Inside Bookshelf, the short name Book is enough to create an object

Inside its containing class, the static nested class is used to create objects in the usual way. The code in Bookshelf's main method writes new Book(...) with the short name, because the code sits inside the class that contains Book. The output of this program is Dune, and the trace is simply the object being created and its title printed.

Full Names and the Dollar Sign

A name for a static nested class is built from two pieces joined by a period. The first piece is the name of the class in which the nested class is declared. The second piece is the name of the nested class itself. The result is called the full name, and it is the name a program must use whenever it refers to the nested class from outside its containing class. For the source example, the full name is WireFrameModel.Line.

WireFrameModelouter class name.period joins the two piecesLinenested class name
How does the name written in source (Outer.Inner) break down, and which form do I write when referring to the nested class from outside the outer class?

The full name WireFrameModel.Line uses a period, but the class file is named WireFrameModel$Line.class and uses a dollar sign. Both forms refer to the same nested class. The period form is what your source code writes when it refers to the class from outside. The dollar form is the name that appears on disk in the build output. Keep the two apart: you write the period form in code, and you look for the dollar form in the folder.

Using the Nested Class Inside and Outside

java
Output
Emma
Notes on the code
  • Library is a different class, so it sits outside Bookshelf
  • Bookshelf.Book is the full name, containing class then period then nested class
  • The commented line uses the short name Book, which this class cannot see
Worked example

Tracing a reference from outside the containing class

Library's main method needs a Book object. Which name must it use, and what does that name point to?

  1. 1
    Locate the containing class

    Book is declared inside Bookshelf, so Bookshelf is the outer class.

  2. 2
    Check where the reference sits

    The reference is written in Library, which is outside Bookshelf. Inside Bookshelf the short name works, but here it does not.

  3. 3
    Build the full name

    Join the outer class name, a period, and the nested class name, giving Bookshelf.Book.

  4. 4
    Create the object

    new Bookshelf.Book("Emma") creates a Book, and its title field holds Emma, which prints as Emma.

Result

Outside the containing class, the nested class must be referred to as Bookshelf.Book. The short name Book works only inside Bookshelf.

What do you think happens?

In the Library class, the line Book c = new Book("Emma"); is uncommented. Does the program compile?

  • Yes, because Book is the nested class name

  • No, because outside the containing class the nested class must be referred to by its full name

Reveal answer
Answer:

No, it does not compile. The line that uses the short name Book breaks the program.

The source states that outside its containing class, the nested class must be referred to by its full name, containing class name, period, nested class name. Writing only Book from Library is a naming mistake. The compiler reports the error on that line, so the fix is to change it to Bookshelf.Book.

Mistakes That Break Nested Class References

  • Common mistake

    Using only the nested class name from outside the containing class

    What it looks like

    In Library, writing Book c = new Book("Emma"); when Book is declared inside Bookshelf.

    Why it fails

    Outside its containing class, the nested class must be referred to by its full name. The short name is only enough inside the containing class.

    Do this instead
    Write Bookshelf.Book c = new Bookshelf.Book("Emma");
  • Common mistake

    Looking for the nested class inside the outer class's file

    What it looks like

    Opening WireFrameModel.class expecting to find Line's compiled code there.

    Why it fails

    The nested class is stored in its own file, not inside the outer class's file.

    Do this instead

    Look for WireFrameModel$Line.class in the build output.

  • Common mistake

    Writing the dollar form in source code

    What it looks like

    Writing WireFrameModel$Line in a Java statement instead of WireFrameModel.Line.

    Why it fails

    The dollar form is the name of the class file on disk. Source code uses the period form, the full name.

    Do this instead

    Use WireFrameModel.Line in source, and expect WireFrameModel$Line.class in the build folder.

  • Common mistake

    Assuming one source definition with a nested class yields a single class file

The Static Structure of the Containing Class

The phrase part of the static structure matters. The source makes an analogy with static member variables. A static variable belongs to its class rather than to any single object created from that class. In the same way, a static nested class belongs to the containing class itself. Each object of the outer class does not carry its own copy of the nested class. The nested class is attached to the class as a whole.

WireFrameModelouter classLinestatic nested classWireFrameModel.Linefull name from outsidestatic member ofreached through
Does the static nested class belong to the outer class itself rather than to any outer object, and how is it reached through the outer class name?

The diagram shows the relationship in words. The nested class Line is a static member of the outer class WireFrameModel, so it is reached through the outer class name. Its full name is WireFrameModel.Line. This is why a program outside the containing class has to write the outer class name in front of it.

Checking Your Understanding

EASY

A source file defines a class Garage that contains a static nested class named Wheel. Before compiling, predict the name of the nested class's class file. Then write the full name you would use to create a Wheel from a class called Showroom, which sits outside Garage.

Hints
  • The class file name combines the outer class name, a dollar sign, and the nested class name.
  • Outside the containing class, the full name joins the outer class name, a period, and the nested class name.
MEDIUM

A class Showroom uses the line Wheel w = new Wheel(); and it does not compile. Explain in one sentence why, and state which name the line must use.

Hints
  • Ask whether Showroom is inside Garage's body.
  • Compare the short name with the full name from the previous question.

Key Takeaways

  • Compiling one source definition that contains a nested class produces two separate class files: one for the outer class and one for the nested class.
  • The nested class file is named by combining the outer and nested class names with a dollar sign, such as WireFrameModel$Line.class.
  • A static nested class is declared inside another class with the static modifier, and it belongs to the containing class as part of its static structure, much as a static variable belongs to its class.
  • Inside the containing class, the nested class can be used with its short name. Outside it, the full name is required: the outer class name, a period, and the nested class name, as in WireFrameModel.Line.
  • When a reference to a nested class fails to compile, check whether the line uses only the short nested name from outside the containing class.