Nest classes with care

In Java, you can nest classes within other classes. This feature is very useful when you need it, but it can be easily abused.

When you have a choice, you should declare your nested classes as static. The reason is that non-static nested classes (inner classes) are tightly coupled to the enclosing parent, while static nested classes aren't. This extra coupling can sometimes cause problems. In general, static nested classes are safer than non-static ones, and less prone to error.

Secondly, you should very rarely use deep levels of nesting.

The terminology for nested classes is a bit confusing. Here's a reminder of the hierarchy:

nested class
  static
  inner class (non-static)
    regular, not within a method or constructor
    inside a method or constructor
      anonymous
      local
Some more reminders: Here's a class which sketches all the different types of nested class:

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public final class MakeMovie {

  /**
    Static, since has no need of being attached to a parent instance.
   */
  static final class Actor {
    Actor(String aName){
      fName = aName;
    }
    String getName(){ 
      return fName; 
    }
    private String fName;
  }

  /**
    Non-static (inner) class, since casting will need to know about the 
    movie's data - its name, director, and budget.
  */
  final class Casting {
    void chooseFrom(List<Actor> aActors){
      //can reference the parent's data directly:
      if(fDirector.equals("Stanley Kubrick")){
        //elided...
      }
    }
    List<Actor> getSelectedCast(){ 
      return fSelectedCast; 
    }
    //static void doThis(){} //does not compile, since static
    private List<Actor> fSelectedCast;
  }
  
  void wrapParty(){
    Timer timer = new Timer();
    //anonymous class - the implementation of TimerTask
    //this is usually how anonymous classes are used - to define a single method
    timer.schedule(
      new TimerTask(){ 
        @Override public void run() {
          //elided...
        };
      },
      new Date()
    );
  }

  void shootScene(final int aSceneNumber){
    //local class - this style seems to be rather rare
    class Camera {
      void shoot(){
        //won't compile unless aSceneNumber is final:
        System.out.println(aSceneNumber);
      }
    }
    Camera camera = new Camera();
    camera.shoot();
  }
  
  //elided...

  private String fName;
  private String fDirector;
  private BigDecimal fBudget;

} 


Would you use this technique?
Yes   No   Undecided   
© 2014 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on September 21, 2013.
Over 2,000,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -