Mike Slinn

Connoisseur of Technology

Instantiating Java Inner Classes

2005-12-30 / All Blog posts

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!) ;)


Contact Mike Slinn

Unless you are a recruiter, in which case you should not try to make contact!

  • Email
  • Direct: 514-418-0156
  • Mobile: 650-678-2285

Disclaimer

The content on this web site is provided for general information purposes only and does not constitute legal or other professional advice or an opinion of any kind. Users of this web site are advised to seek specific legal advice by contacting their own legal counsel regarding any specific legal issues. Michael Slinn does not warrant or guarantee the quality, accuracy or completeness of any information on this web site. The articles published on this web site are current as of their original date of publication, but should not be relied upon as accurate, timely or fit for any particular purpose.

Accessing or using this web site does not create a client relationship. Although your use of the web site may facilitate access to or communications with Michael Slinn via e-mail or otherwise via the web site, receipt of any such communications or transmissions does not create a client relationship. Michael Slinn does not guarantee the security or confidentiality of any communications made by e-mail or otherwise through this web site.

This web site may contain links to third party web sites. Monitoring the vast information disseminated and accessible through those links is beyond Michael Slinn's resources and he does not attempt to do so. Links are provided for convenience only and Michael Slinn does not endorse the information contained in linked web sites nor guarantee its accuracy, timeliness or fitness for a particular purpose.


comments powered by Disqus

© 1976-2020, Michael Slinn. All rights reserved.