Search code examples
javaclassnested

When is really useful to use a nested Java class?


Could you give me a concrete example where a nested java class is useful? I am studying it, I understand how it works but I can not imagine a real situation where its use is really necessary.

Thank you so much

Marco


Solution

  • The most concise summary of when to use a nested class is: when that class is logically part of the outer class' API, or when it encapsulates behavior specific to the outer class.

    For example, Map.Entry: it's an entry in a mapping. It's logically part of Map's API, so it makes sense to put it inside Map.

    Another common example is Builder classes: you use a Builder to make a thing, so it makes sense to put it inside that thing.

    These are classes that you only really use in the context of using the outer classes: sometimes you might use a Map.Entry by itself as some sort of pair class; and sometimes you might want to use a Builder by itself, for example as a parameter to a method which puts things into that builder, but doesn't actually do the building itself. These cases are probably rarely far from code that also uses the outer class too: you're still using some aspect the outer class' API, so they do still logically belong to that API.

    You could put such classes at the top level, alongside the "main" class. There are a few reasons why you might not want to do this:

    • It clutters the namespace. If you've got classes Foo, Bar, Baz etc, having FooBuilder, BarBuilder, BazBuilder at the top level just makes it harder to see the "useful" top level classes.
      • Google's protocol buffers generate a Builder class for every message type. Given the number of protocol buffers used in Google code, this clutter would be far too cumbersome.
    • Nested classes have access to private fields of the outer class, which may help you do certain things without unnecessarily exposing those fields.
    • You can refer to nested classes by qualifying the outer name, e.g. Outer.Builder, rather than having to explicitly import some.pkg.OuterBuilder as well as import some.pkg.Outer. Admittedly, I don't really care about the number of imports, since I just keep them collapsed in intellij.

    You can also use them to encapsulate internal logic or intermediate state in the class: for example, I like to define private nested classes when I find myself passing around the same N parameters between private methods in a class. This is stuff that you don't want people outside your class to care about; it's merely convenient inside the class.