Adverts
Java possesses five different types of class construct and if one is to develop quality software it is important to know where to use each type. It can sometimes be difficult to know exactly which variant should be used in a particular situation as often more than one will fit. To make matters worse there are generally many ways that a particular problem can be solved. This article will discuss the various class types and give indicators as to when they should be used.
Top Level Classes
A top level class is the one that all Java developers will be familiar with as without it one can not develop software at all. A typical top level class can be seen below:
public class Foo {
public static void main(String[] args) {
}
}
This is the simplest, runnable, top level class that could be developed and lives in a file called Foo.java. Without actually checking I would guess that 90% or more classes are top level. Each class encapsulates some data or functionality that logically belongs on its own. If in doubt about which type of class to use a top level class is probably the safest choice as it will be easier to correct any mistakes later.
Static Member Classes
Static member classes (sometimes called static inner classes although they aren't strictly inner) are the first and most common type of nested class. A nested class is defined inside the body of an enclosing class and should only be present to assist the enclosing class. There is no limit to the depth of the class nesting but it is uncommon to see more than one level and very uncommon to see more than two (in more years than I care to think about developing Java I have never seen a triple nested class).
A very simple static member class is shown below. As with the top level class this is as simple as it can be and is just to show the syntax:
public class Nest {
private static class Nested {
}
}
Static member classes can be thought of as regular classes that are simply defined inside another class. They have complete access to all the enclosing classes static member variables and functions. All the rules regarding accessibility of the member class are the same as for any other static member of the class. So, for instance, if it's private only the enclosing class can access it.
public class Nest {
private static String var = "foo";
private static class Nested {
public Nested() {
var = "bar";
}
}
}
The most common use of static member classes is as an auxiliary class that only makes sense when used in conjunction with its enclosing class. An example of this is in the Java library is in he Map interface which includes the Map.Entry static interface. Although this example uses interfaces rather than classes the intention is exactly the same. Interfaces are used in order to make it easier to switch to a different implementation at a later date.
Non-Static Inner Classes
There is only one small difference between the declaration of a static and non-static member class but in terms of functionality the difference is huge. To define a non-static inner class use the same syntax as for static member classes but don't include the static key word. For Example:
public class Nest {
private String var = "foo";
private class Nested {
public Nested() {
var = "bar";
}
}
}
The most important difference between static member classes and non-static inner classes can be seen in this example. Each instance of the inner class is implicitly associated with an instance of its enclosing class. This allows the inner class to directly access the non-static member variables and functions of its enclosing instance. Since a non-static inner class maintains a reference to its enclosing class an instance of a non-static inner class can not be created unless there is an instance of the enclosing class. Instances of the inner class maintain a reference to their enclosing instance which is assigned automatically upon object creation. If your member class doesn't require access to the enclosing instance make it static to save resources.
Non-static inner classes are useful as adaptors that allow a class to appear to be something else. For example one can view the keys in a Map as a Set. This is handled by the creation of an inner class that implements the Set interface which is then returned to the user. Iterators are a similar example. When one requests an Iterator from a collection what one receives is an inner class that implements the iterator interface. The class itself needs to be non-static so that it can access the contents of the enclosing instance.
Due to the restriction that a non-static inner class can't exist without an enclosing instance it is uncommon to see non-static inner classes that aren't private or at least package protected. Static member classes, in contrast, are frequently public.
You might now like to go onto Java Class Types Part II