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 localSome more reminders:
extends
or implements
; no constructor
final
items that are in scope; this is
the rarest form 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 name){ this.name = name; } String getName(){ return name; } private String name; } /** 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> actors){ //can reference the parent's data directly: if(director.equals("Stanley Kubrick")){ //elided... } } List<Actor> getSelectedCast(){ return selectedCast; } //static void doThis(){} //does not compile, since static private List<Actor> selectedCast; } 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 sceneNumber){ //local class - this style seems to be rather rare class Camera { void shoot(){ //won't compile unless sceneNumber is final: System.out.println(sceneNumber); } } Camera camera = new Camera(); camera.shoot(); } //elided... private String movieName; private String director; private BigDecimal budget; }