Concepts / Inner Classes in Java

Inner Classes in Java

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.

  • 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 next to that larger type, so the code describing one concept lives together. The way a nested class is placed changes how it is named, referred to, and used, and that naming rule is the main skill this article builds.

Anatomy of 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 declaration of a static nested class looks almost identical to the declaration of any other class. Two things are added. First, the class is written inside the body of another class. Second, the keyword static appears as part of its declaration. Nothing else about the way the class is written needs to change.

Predicting the Name Each Location Needs

Before reading the rule, commit to a prediction. The source uses a class called WireFrameModel that contains a static nested class called Line. Ask yourself: when code sits inside WireFrameModel, and when code sits outside it, does the name used for Line stay the same?

What do you think happens?

Code outside WireFrameModel needs to refer to the nested class Line. Which name must it use?

  • Line alone, the same as inside the class

  • WireFrameModel.Line, the containing class name, a period, then the nested class name

  • Line.WireFrameModel, the nested class name first

Reveal answer
Answer:

WireFrameModel.Line

Outside its containing class, the nested class must be referred to by its full name: the containing class name, a period, and the nested class name. Inside the containing class, the nested class can be used in the usual way.

Tracing Names Inside the Containing Class

The source describes WireFrameModel, a set of lines in three-dimensional space and the kind of model used to represent three-dimensional objects in graphics programs. Its nested class Line represents one line, stored as two endpoints. The example below is an original illustration with a different containing class, so the naming rule can be checked on fresh code. Trace which name appears inside the containing class and which name appears in the main method.

Code walkthrough
public class Library {
    static class Book {
        String title;
        Book(String title) {
            this.title = title;
        }
    }

    public static void main(String[] args) {
        Book b = new Book("Dune");
        System.out.println(b.title);
    }
}
  1. 1
    The class Library is the outer class. Its body contains the declaration of Book.
  2. 2
    The keyword static in static class Book makes Book a static nested class.
  3. 3
    Inside main, which is part of Library, the line new Book("Dune") uses the simple name Book, because the code is inside the containing class.
  4. 4
    The program prints the title stored in the object, which is Dune.
  • Library is the containing (outer) class
  • static class Book is the static nested class, declared inside Library's body
  • Book is used by its simple name inside Library, where objects are created in the usual way
Output
Dune

The key point is where the code sits. The simple name Book works here only because the reference is inside Library. The name is not changed by the nested class itself; the location of the reference decides which name is required.

Reaching In From Outside the Class

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 the full name, and it is the name a program must use whenever it refers to the nested class from outside its containing class. In the source's example, the full name is WireFrameModel.Line.

WireFrameModelcontaining class.period joins the two partsLinestatic nested class name
In the name WireFrameModel.Line, which part identifies the containing class, which part identifies the nested class, and how is the name read from outside?
Before
// in a separate class, outside Library
Book b = new Book("Dune");

The simple name Book is used outside the containing class, so the reference does not follow the full-name rule and the program breaks at this line.

After
// in a separate class, outside Library
Library.Book b = new Library.Book("Dune");

The full name Library.Book is used, so the reference names the nested class correctly from outside its containing class.

The Static Structure of the Outer Class

The phrase part of the static structure matters. A static nested class belongs to the containing class itself, in the same way that a static member variable belongs to its class rather than to any single object created from it. So the nested class is not something each object of the outer class carries around. It is attached to the class as a whole.

WireFrameModelcontaining classOther membersLinestatic nested classcontainscontains
Which class contains which, and how does the nested class sit within the outer class's static structure?

The diagram shows the containment. WireFrameModel holds other members, and it also holds the static nested class Line. Line belongs to WireFrameModel as a class-level part of it, which is why the full name WireFrameModel.Line is the name that identifies it from outside.

Mistakes in Naming a Nested Class

  • Common mistake

    Using the simple name of the nested class from outside its containing class

    What it looks like

    Book b = new Book("Dune"); written in a separate class

    Why it fails

    Outside the containing class, the nested class must be referred to by its full name.

    Do this instead
    Library.Book b = new Library.Book("Dune");
  • Common mistake

    Reversing the two parts of the full name

    What it looks like

    Book.Library used to refer to the nested class

    Why it fails

    The full name is the containing class name, then a period, then the nested class name.

    Do this instead

    Library.Book

  • Common mistake

    Assuming the full name is required everywhere

    What it looks like
    Writing Library.Book b = new Library.Book("Dune"); inside Library
    Why it fails

    The full name rule applies to references from outside the containing class. Inside the containing class, the nested class can be used in the usual way.

    Do this instead
    Inside Library, write Book b = new Book("Dune");

Finding the Line That Breaks

MEDIUM

Read the three lines below. Each refers to the static nested class Book from the Library example. Decide which line will not compile when it sits outside the Library class, and explain the rule that makes it fail. Lines are numbered for reference.

Line 1: Library.Book first = new Library.Book("Emma");
Line 2: Book second = new Book("Emma");
Line 3: Library.Book third = new Book("Emma");
Hints
  • Ask whether each line is outside Library, and whether it uses the full name.
  • Line 3 mixes the two forms. Check each name in it separately.

Key Takeaways

  • 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.
  • Inside its containing class, a static nested class can be used to create objects in the usual way.
  • Outside its containing class, the nested class must be referred to by its full name: the containing class name, a period, and the nested class name, as in WireFrameModel.Line.
  • The nested class belongs to the class itself, in the same way that a static member variable belongs to the class rather than to individual objects.