Java programming techniques

switch on String enum

In circumstance such as parsing of text, one often wants multiple control paths based on the value of a string token. Many languages have special syntax for this purpose. Java 5 provides in its enum and switch a convenient means to achieve this, although the technique is not obvious.

Java switch cases must be compile-time constants: enum is ideal for this. However, the switch is type-safe, and so must take an enum object of the same type as its case statements. How does one convert a String to an enum?

A constructor will not work. An enum constructor is special in that it is called automatically at initialization to construct the enum object, but cannot be called directly in code. Java enums cannot be instantiated. But we need to convert a String to an enum at run time.

The trick is the Enum.valueOf() method, which returns the name of the enum constant as a String.

Another concern is that in converting a String to an enum, valueOf() throws an exception if the String isn’t exactly one of the enums.

public class
SwitchEnumString
{
        enum
	Beatle {
                John, Paul, George, Ringo,
		none;

		//  Here, the choice was to catch the exception at a low level,
		//  and return a 'none' enum.  But there are other ways.
                static Beatle
                fromString( String str )
                {
			try
			{
				return Beatle.valueOf( str );
			}
			catch( Exception e )
			{
				return none;
			}
                }
        }

	public static void
	main( String[] args )
	{
		if( args.length == 0 )
			System.err.println( "Usage:\n" +
			"\tSwitchEnumString <list of first names of Beatles>" );

		for( String firstName : args )
			System.out.println( getLastName( firstName ) );
	}

	static String
	getLastName( String first )
	{
		switch( Beatle.fromString( first ) )
		{
		case John:   return "Lennon";
		case Paul:   return "McCartney";
		case George: return "Harrison";
		case Ringo:  return "Starr";
		default:     break;
		}
		return "";
	}
}

nested classes—when and how

Java has several features called “nested” or “enclosed” classes. One class can defined within the code body of another class’ definition (indeed a class can be defined, within any code block.) The relationship between the inner and outer classes vary with the kind of nesting.

These features do not exist in all object-oriented languages: C++ has nested classes that correspond to Java static nested classes, but nothing corresponding to the non-static ones. It isn’t something essential to object-oriented programming.

Nested classes turn out to be very handy in some circumstances, and can result in cleaner, more transparent code. But they are often misused too.

This is my collection of rules of thumb and techniques for nested classes.

basic use of nested classes

static vs. non-static inner classes

An instance plain inner class (without the static keyword), is dependent on an instance of the outer class. An instance of the inner class can be created only in reference to an instance of the outer class. Importantly, the public and protected members of the outer class are directly accessible to the code of the inner class, as though they were members of the inner class.

Since a non-static inner class is always associated with its containing class, constructors for the inner class are only meaningful in non-static code of the containing class. An instance of the containing class can create as many instances of its inner classes as desired however. CHECK THIS

class Outer {
	private int outerField;

	private void overridable() {
	}

	class Inner {
		void innerMethod() {
			outerField = 0;	// access Outer class member
					// pass this as instance of Outer
			someObject.methodRequiringOuter( Outer.this );
		}

		private void overridable() { // override Outer method
			Outer.overridable(); // call Outer method of same name
		}
	}
} 

The scope keyword static applied to an inner class definition effectively makes it independent of its containing class, except that, to outside code, it must be referred to via the name of the containing class. It is like putting the class in the namespace of the outer class.

Since instances of a static inner class have no direct association with instances of their containing class, they also have no association with non-static members of the containing class.

Careful: The direct access to outer class members has some pitfalls. For instance: The compiler does not check to see if the constructor of an inner class uses an outer class member before that member has been initialized.

anonymous inner classes

A class may also be defined anonymously. Anonymous classes are commonly used to create Adaptor classes, which only require one method to be overridden.

The anonymity of these classes reflects the fact that their identity isn’t important to the class model. They are defined only for the specific purpose at hand.

	private MyType
	makeMyType() {
		return new Adaptor() {
			// overridden Adaptor members
		}
	} 

The down-sides are: (1) the notation and even the concept is kind of weird, and very Java-specific. (2) if such an object is returned by a function, conventional code indentation will have its code indented more than that of a named class would be.

Note that there is no sense of overriding a constructor of a superclass of an anonymous class. However, a parameter list in the parentheses following the superclass name will be passed to a matching constructor of a superclass.

Another option is to define an instance of an anonymous subclass of an Adaptor in a variable. This at least doesn’t require deeper indentation.

	private Adaptor myVarName = new Adaptor() {
		// overridden Adaptor members } 

The down-side of this technique is, the variable’s initialization code must execute before it is passed to some method (of course), but with nested classes, it may be unclear which code is executed first.

referring to outer class from the inner

The instance of the containing class is referred to from an instance of an inner class by the special notation outer.this. Similarly, if the name of a member of the inner class shadows the name of a member of the containing class, the containing class member can be accessed by the special notation outer.member

when to use nested classes

when to use a normal inner class

The natural purpose for nested classes, is to model a notion of containment.

For instance, a special dialog window might contain a class of controls that are meaningful only within that dialog.

The coding advantage of properly modeled inner classes is, the code doesn’t have to set up references between the contained and container class. A normal inner class already has access to its container members.

On the other hand, a class definition is made longer and possibly harder to follow by the presence of an inner class. Unless the nesting means something in the model, it is probably a mistake.

Also, for reasons of readability, inner classes ought to be very simple in structure, with very few members, or simple lists. Likewise, deep nesting of classes would be hard to defend. The loss of readability of complex inner classes probably outweighs the advantages gained by the affinity with outer classes.

A named, non-static inner class should satisfy all these criteria:

  1. instances of inner class are somehow conceptually contained by instances of the outer class
  2. inner class code is simple
  3. inner class code benefits from direct access to outer class’ members.

when to use a static inner class