Java – Why Prefer Non-Static Inner Classes Over Static Ones?

classclass-designjavastatic-keyword

This question is about whether to make a nested class in Java to be a static nested class or an inner nested class. I searched around here and on Stack Overflow, but couldn't really find any questions regarding the design implications of this decision.

The questions I found are asking about the difference between static and inner nested classes, which is clear to me. However, I have not yet found a convincing reason to ever use a static nested class in Java — with the exception of anonymous classes, which I do not consider for this question.

Here's my understanding of the effect of using static nested classes:

  • Less coupling: We generally get less coupling, as the class cannot directly access its outer class's attributes. Less coupling generally means better code quality, easier testing, refactoring, etc.
  • Single Class: The class loader need not take care of a new class each time, we create an object of the outer class. We just get new objects for the same class over and over.

For an inner class, I generally find that people consider access to the outer class's attributes as a pro. I beg to differ in this regard from a design point of view, as this direct access means we have a high coupling and if we ever want to extract the nested class into its separate top-level class, we can only do so after essentially turning it into a static nested class.

So my question comes down to this: Am I wrong in assuming that the attribute access available to non-static inner classes leads to high coupling, hence to lower code quality, and that I infer from this that (non-anonymous) nested classes should generally be static?

Or in other words: Is there a convincing reason why one would prefer a nested inner class?

Best Answer

Joshua Bloch in Item 22 of his book "Effective Java Second Edition" tells when to use which kind of nested class and why. There are some quotes below:

One common use of a static member class is as a public helper class, useful only in conjunction with its outer class. For example, consider an enum describing the operations supported by a calculator. The Operation enum should be a public static member class of the Calculator class. Clients of Calculator could then refer to operations using names like Calculator.Operation.PLUS and Calculator.Operation.MINUS.

One common use of a nonstatic member class is to define an Adapter that allows an instance of the outer class to be viewed as an instance of some unrelated class. For example, implementations of the Map interface typically use nonstatic member classes to implement their collection views, which are returned by Map’s keySet, entrySet, and values methods. Similarly, implementations of the collection interfaces, such as Set and List, typically use nonstatic member classes to implement their iterators:

// Typical use of a nonstatic member class
public class MySet<E> extends AbstractSet<E> {
    ... // Bulk of the class omitted

    public Iterator<E> iterator() {
        return new MyIterator();
    }

    private class MyIterator implements Iterator<E> {
        ...
    }
}

If you declare a member class that does not require access to an enclosing instance, always put the static modifier in its declaration, making it a static rather than a nonstatic member class.