Mike Slinn
Mike Slinn

Instantiating Java Inner Classes

Published 2005-12-30.
Time to read: 1 minutes.

This page is part of the posts collection, categorized under Java.

I've been writing Java code for years. Today I learned something new. I have been adding a new feature to Zamples that was best expressed as a doubly nested inner class. The hierarchy looks like this:

public class CodeRange {
   public CodeRange(String str) { /* ... */ }
public class RangeSpec { public RangeSpec(int i, int j) { /* ... */ } public RangeSpec(RangeItem start, RangeItem end) { /* ... */ }
public class RangeItem { public RangeItem(String str, int i) { /* ... */ } } } }

When it came time to write JUnit tests, I needed to instantiate the hierarchy. The syntax surprised me:

CodeRange.RangeSpec.RangeItem range =
   new CodeRange("test").new RangeSpec(1, 1).new  RangeItem("middle", 3);

Not exactly intuitive, eh? It gets even more interesting when trying to write unit tests for the second RangeSpec constructor, the one that accepts two RangeItems. I found I had to create a protected no-args constructor for RangeSpec with an empty body, plus a method within RangeSpec to create RangeItems on demand:

/** For JUnit only */
   protected RangeSpec() {}
/** For JUnit only */ protected RangeItem newRangeItem(String searchString, int offset) { return new RangeItem(searchString, offset); }

Now I could write my test case setup code:

codeRange = new CodeRange(code, "");
   CodeRange.RangeSpec.RangeItem rangeItemStart =
      codeRange.new RangeSpec().newRangeItem("middle", 3);
   CodeRange.RangeSpec.RangeItem rangeItemEnd =
      codeRange.new RangeSpec().newRangeItem("back", 0);
CodeRange.RangeSpec rangeSpec = codeRange.new RangeSpec(rangeItemStart, rangeItemEnd); /* ... */

Everything I read about doubly nested classes amounted to a warning to the effect that they should be avoided. I never had occasion to need this type of solution before, however the particular problem I am solving yields very nicely to this approach. It is simple, elegant and efficient. Don't believe everything you read (except this blog!) 😉.