Nested classes can be static or non-static (also called an inner class). How do you decide which to use? Does it matter?

Solution:

The key difference between is that inner classes have full access to the fields and methods of the enclosing class. This can be convenient for event handlers, but comes at a cost: every instance of an inner class retains and requires a reference to its enclosing class.

With this cost in mind, there are many situations where we should prefer static nested classes. When instances of the nested class will outlive instances of the enclosing class, the nested class should be static to prevent memory leaks. Consider this implementation of the factory pattern:

        public interface WidgetParser {
            Widget parse(String str);
        }
      
        public class WidgetParserFactory {
            public WidgetParserFactory(ParseConfig config) {
                ...
            }
      
            public WidgetParser create() {
                new WidgetParserImpl(...);
            }
      
            private class WidgetParserImpl implements WidgetParser {
                ...
              
                @Override public Widget parse(String str) {
                    ...
                }
            }
        }

At a glance, this design looks good: the WidgetParserFactory hides the implementation details of the parser with the nested class WidgetParserImpl. However, WidgetParserImpl is not static, and so if WidgetParserFactory is discarded immediately after the WidgetParser is created, the factory will leak, along with all the references it holds.

WidgetParserImpl should be made static, and if it needs access to any of WidgetParserFactory’s internals, they should be passed into WidgetParserImpl’s constructor instead. This also makes it easier to extract WidgetParserImpl into a separate class should it outgrow its enclosing class.

Inner classes are also harder to construct via reflection due to their “hidden” reference to the enclosing class, and this reference can get sucked in during reflection-based serialization, which is probably not intended.

So we can see that the decision of whether to make a nested class static is important, and that one should aim to make nested classes static in cases where instances will “escape” the enclosing class or if reflection on those nested classes is involved.

0 answers