Concepts / Static Member Variables

Static Member Variables

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 that the code describing one concept lives together. The rest of this article shows how that placement changes the way the inner class is named, referred to, and used.

Keep one question in mind as you read: when the code uses the inner class's name, is it inside the containing class or outside it? As you will see, that single detail decides which name the code must write.

What a Static Nested Class Is

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. The class is written inside the body of another class, and the keyword static appears as part of its declaration. Nothing else about the way the class is written needs to change.

The phrase 'part of the static structure' matters. The source compares a static nested class 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 as a whole. It is not something each object of the outer class carries around. It is attached to the class itself.

Tracing the WireFrameModel Example

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

The following sketch is an original illustration, not taken from the source. It shows the shape of the code: the Line class sits inside the body of WireFrameModel, and it carries the static modifier in its declaration. Trace the two places where the name Line appears inside the outer class.

java
Notes on the code
  • static class Line is declared inside the body of WireFrameModel
  • Line is written by its short name because the code is inside WireFrameModel
  • new Line() creates an object in the usual way from inside the containing class

Inside WireFrameModel, the program stays within its own class, and the short name Line is enough. The source states that, inside its containing class, a static nested class can be used to create objects in the usual way. The next section shows what changes when the code moves outside the containing class.

WireFrameModelouter (containing) classLinestatic nested classother membersremaining members ofWireFrameModelcontainscontains
What contains what, and which members belong to the outer class's static structure versus its other members?

The diagram above shows the containment. Line is one of the things WireFrameModel contains, and the source places it within the static structure of that containing class. The other members are shown separately because the source only says that WireFrameModel holds other members, without describing them further.

Full Names From Outside the Container

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. Outside its containing class, a program must use this full name whenever it refers to the nested class.

For the WireFrameModel example, the full name is WireFrameModel.Line. The diagram below labels each part of that name. Read it from left to right: the outer class, then the separator, then the nested class.

WireFrameModelouter (containing) classname.period separatorLinenested class namefull name
Which parts of the full name are the outer class, the nested class, and the separator, and what happens to a misspelled or wrongly qualified name?

The full name has to be correct at every segment. If the outer class name is misspelled, or if the Line part is written without the outer class in front of it, the reference no longer names the nested class that exists in WireFrameModel. The next example shows a program that writes the full name from a different class.

java
Notes on the code
  • The class Demo is outside WireFrameModel, so the full name is required
  • WireFrameModel.Line is the containing class name, a period, and the nested class name
  • The same full name appears in the declaration and in the new expression

What do you think happens?

In class Demo, which of these declarations will compile, and which one will not?

  • WireFrameModel.Line first = new WireFrameModel.Line(); only

  • Line first = new Line(); only

  • Both declarations compile

Reveal answer
Answer:

Only WireFrameModel.Line first = new WireFrameModel.Line(); compiles from Demo.

The source says that outside its containing class, the nested class must be referred to by its full name, as in WireFrameModel.Line. Writing only Line from Demo does not use that full name, so it is the wrong reference. The same code works inside WireFrameModel, where the short name is enough.

Finding Where a Naming Mistake Breaks

When a program fails to compile because of a nested class name, the useful skill is to find the line that breaks it. Work through the reference in the same order every time: decide whether the code is inside or outside the containing class, and then check whether the name matches the rule for that location.

Worked example

Locating the line that breaks a nested class reference

Class Demo, which is outside WireFrameModel, contains three lines that use the nested class. Which line breaks the program, and why?

  1. 1
    Line 1: WireFrameModel.Line a = new WireFrameModel.Line();

    The reference is outside WireFrameModel, and it uses the full name, containing class name then period then nested class name. This follows the rule in the source.

  2. 2
    Line 2: WireFrameModel.Line b = new Line();

    The declaration uses the full name, but the new expression uses only Line. The two references do not match, and the new expression is written outside the containing class without the full name. This is the line that breaks.

  3. 3
    Line 3: System.out.println(a == null);

    This line refers to the variable a, which was declared on line 1. It does not name the nested class at all, so it cannot be the source of a nested class naming error.

Result

Line 2 is the line that breaks the program, because the new expression writes Line by itself from outside WireFrameModel instead of the full name WireFrameModel.Line.

Mistakes Beginners Make with Nested Names

  • Common mistake

    Using the short name Line from a class outside WireFrameModel

    What it looks like

    Line edge = new Line(); written inside class Demo

    Why it fails

    The source says that outside its containing class, the nested class must be referred to by its full name.

    Do this instead
    Write WireFrameModel.Line edge = new WireFrameModel.Line();
  • Common mistake

    Assuming the static nested class belongs to each object of the outer class

    What it looks like

    Thinking that every WireFrameModel object carries its own separate copy of the Line class

    Why it fails

    The source places a static nested class in the static structure of its containing class, attached to the class as a whole, in the same way a static variable belongs to its class rather than to individual objects.

    Do this instead

    Think of the nested class as belonging to WireFrameModel itself, not to each object created from it.

  • Common mistake

    Misspelling one segment of the full name

    What it looks like

    WireFrame.Line instead of WireFrameModel.Line

    Why it fails

    The full name is built from the containing class name, a period, and the nested class name. A wrong first segment no longer names the containing class.

    Do this instead

    Check each of the two segments against the declared names, and keep the period between them.

  • Common mistake

    Forgetting that the short name is allowed inside the containing class, and adding a full name that is not needed there

Practice Locating Nested Class Names

EASY

A class called Scene contains a static nested class called Node. Write the declaration that a class outside Scene would use to create one Node object. Then write the same creation from inside Scene. Explain why the two versions differ.

Hints
  • Outside the containing class, the full name is the containing class name, a period, and the nested class name.
  • Inside the containing class, the short name is enough to create an object in the usual way.
MEDIUM

A program has a class Viewer outside WireFrameModel. Its main method contains WireFrameModel.Line p = new WireFrame.Line(); on one line and WireFrameModel.Line q = new WireFrameModel.Line(); on the next. Predict which line fails to compile, name the exact segment that is wrong, and state the corrected line.

Hints
  • Compare the containing class name in each new expression with the name in the declaration.
  • The segment to fix is the first one of the full name, the containing class name.

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.
  • The static nested class belongs to the class itself, in the same way that static member variables belong to the class rather than to individual objects.
  • Inside its containing class, the short name is enough to create objects of the nested class 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.
  • When a nested class reference fails, check whether the code is inside or outside the containing class, and then check each segment of the name.