Static Members of a Class
A static nested class has full access to the static members of its containing class, including private ones, and the containing class has full access to the members of the nested class, including private ones.
A Problem Two Classes Share
Imagine two classes that belong together. One holds some data that the other needs to inspect or update while it does its work. The private access modifier normally stops outside code from touching that data, and that is usually a good thing. But when two classes are closely related, that same restriction can feel like it gets in the way. Java offers a structural answer to this problem: place one class inside the other. When the inner class is declared static, the pair gains a specific access relationship, and that relationship is the subject of this article.
Keep one question in mind as you read: if one class is nested inside another, which side is allowed to reach into the other's private members, and does that permission run in only one direction? By the end you should be able to answer that question with precision and to spot where the answer is often misunderstood.
Tracing a Shared Counter
Before we state any rule, we will trace a small program and watch the values change. The program below is an original teaching example. The outer class Bank keeps a private static counter called totalAccounts. Its private static nested class Ledger keeps its own private static counter called entries and has a static method record that updates both counters.
public class Bank {
private static int totalAccounts = 0;
private static class Ledger {
private static int entries = 0;
static void record() {
entries++;
totalAccounts++;
}
}
public static void openAccount() {
Ledger.record();
}
}- 1Line 2 declares the counter
totalAccountsas private static. Only code inside Bank is supposed to see it under ordinary rules. - 2Line 4 declares the nested class Ledger as private static. Because it is private, only code inside Bank can use it.
- 3Line 5 declares entries, a private static member of the nested class.
- 4Lines 7 to 10 define record. It increments entries in the nested class and also increments
totalAccountsin the containing class, which the nested class is allowed to do. - 5Lines 13 to 15 define
openAccountin the containing class. It calls Ledger.record, which the containing class is allowed to do because it contains the nested class.
totalAccountsis private to Bank, but Ledger is nested inside Bank and can reach it- Ledger is declared private, so only code inside Bank can name it
- entries is private to Ledger, and Bank may reach it as well because Bank contains Ledger
openAccountis in the containing class and calls into the nested class
totalAccounts = 0
entries = 0Both static counters start at zero before any call is made.
totalAccounts = 1
entries = 1openAccount calls record once. Ledger.record increments entries to 1, and it also increments totalAccounts to 1.
Following one call through both classes
Starting from both counters at zero, what are the values of totalAccounts and entries after Bank.openAccount runs two times?
- 1First call
openAccountcalls Ledger.record. Inside record, entries becomes 1 andtotalAccountsbecomes 1. - 2Second call
openAccountruns again and calls record again. entries becomes 2 andtotalAccountsbecomes 2. - 3Check the access
Every step that touched a private member was performed by code in one of the two classes. The nested class touched the containing class's private counter, and the containing class called into the nested class's private structure. No getter or setter was needed.
After two calls, totalAccounts is 2 and entries is 2.
Two-Way Access Between the Classes
The central rule is that the two classes trust each other. A static nested class has full access to the static members of its containing class, and this access reaches even the members marked private. Turning the relationship around, the containing class has full access to the members of the nested class, including any that are marked private. Neither side needs a getter, a setter, or any other public door to reach across. The privacy boundary is not a barrier between these two classes.
The access is deliberate and specific. It comes from the structure of the nesting itself. Code elsewhere in the program does not inherit this permission just because it sits in the same package or the same project. The source is explicit that being in the same package does not grant access to a private nested class.
Read the diagram as a pair of arrows. The nested class reaches upward into the private members of its container. The container reaches downward into the private members of the nested class. Both arrows exist at the same time, and that is what makes the arrangement two-way rather than one-way.
Where the Code Must Be Written
The access rule above concerns the members inside the two classes. A second rule concerns the nested class itself. A nested class can be declared private, and such a class can only be used inside the class in which it is nested. Its existence is visible to its container, and nothing outside that container can name it or create objects from it. Whether a piece of code may use the private nested class therefore depends on where that code is written, not on which package or file it lives in.
The tree-like picture is useful because the usability of a private nested class follows its place in the structure. Code inside the containing class is inside the zone where the private nested class is usable. Code located elsewhere, with no nesting relationship to the container, falls outside that zone and cannot use the nested class at all.
What do you think happens?
Suppose a separate top-level class called Auditor, in the same package as Bank, tries to call Bank.Ledger.record(). Will it compile?
Reveal answer
No. Auditor cannot use the private nested class Ledger.
Ledger is private, so it is usable only inside Bank. Being in the same package does not grant access to a private nested class, so Auditor has no path to name or call it.
- Auditor is outside the containing class Bank
- Ledger is private, so this reference is not allowed from here
Why Choose Nesting
The main benefit of a nested class is selective sharing. You can let one class see the private internals of another without making those internals generally available to every other class in the program. Ordinary private members stay hidden from the rest of the world, while the one partner class that genuinely needs them is given a path in.
| Design choice | Who can reach the shared internals | What the design says about the relationship |
|---|---|---|
| Private static nested class | Only the containing class and the nested class | The two classes are closely related and share narrow internal details |
| Public top-level class with public members | Any code that can see the class | The internals are open to the whole program, which widens the surface other code can depend on |
| Top-level class with private members and no nesting | Only code inside that same class, so a partner needs public getters or setters | The partner must go through public doors, which is less selective than a nested arrangement |
How nesting limits visibility compared with wider alternatives
Common Misunderstandings About Privacy
The two-way trust between a containing class and its static nested class is easy to misremember. The following misunderstandings come up often, and each one is contrasted with the correct rule.
Common mistake Assuming that a private nested class is visible to the whole package
What it looks likeAuditor, in the same package as Bank, tries to use Bank.Ledger
Why it failsBeing in the same package does not grant access to a private nested class. Only code inside the containing class can use it.
Do this insteadDecide usability by where the code is written. Code outside the containing class cannot use the private nested class.
Common mistake Believing that the containing class needs a getter to read the nested class's private members
What it looks likeBank tries to read Ledger.entries through a public getter that was never written
Why it failsThe containing class has full access to the members of the nested class, including those marked private. No public door is required.
Do this insteadRead the private member directly from the containing class when the code is inside it.
Common mistake Thinking the access runs in only one direction
What it looks likeConcluding that Ledger can read Bank's private counter, so Bank cannot read Ledger's private counter
Why it failsThe source describes the relationship as two-way. Both classes reach each other's private members.
Do this insteadCheck both arrows. The nested class reaches up into the container, and the container reaches down into the nested class.
Common mistake Assuming that nesting is always the right way to share data
Why it failsThe source frames nesting as appropriate for a genuinely close relationship with narrow sharing. Using it for loosely related classes can hide a design problem.
Do this insteadBefore nesting, ask whether the two classes truly belong together and whether only one partner needs the data.
Practice Reasoning About Access
Using the Bank and Ledger program from earlier, decide whether each of the following is allowed. (a) A method inside Bank reads Ledger.entries directly. (b) A method inside Ledger increments Bank.totalAccounts. (c) A class Teller in a different file of the same package calls Bank.Ledger.record(). For each, name the rule from this article that justifies your answer.
Hints
- Ask which class the code sits inside, since that determines what it can reach.
- The containing class and the static nested class each have full access to the other's private members.
- Being in the same package is not enough to use a private nested class.
Key Takeaways
- A static nested class has full access to the static members of its containing class, including private ones, and the containing class has full access to the members of the nested class, including private ones.
- The two-way access exists because of the nesting structure itself. It lets two closely related classes share private internals without exposing them to the rest of the program.
- A nested class declared private can only be used inside the class in which it is nested. Being in the same package does not grant access.
- Choose nesting when the relationship between the two classes is genuinely close and the sharing is genuinely narrow, not as a general way to avoid designing visibility.