Tag Archives: enum

Java Enum Puzzler

Recently, I ran into an interesting bit of code related to Java enumerations. Here’s a contrived minimal sample:

/*
 * Some arbitrary resource type
 */
interface Resource {
	public Resource getResource();
}

enum A implements Resource{
	ALPHA (B.BRAVO);
	
	private Resource res;
	private A (Resource res){ this.res = res; }
	public Resource getResource(){ return res; }
}

enum B implements Resource{
	BRAVO (C.CHARLIE);

	private Resource res;
	private B (Resource res){ this.res = res; }
	public Resource getResource(){ return res; }

}

enum C implements Resource{
	CHARLIE (A.ALPHA);

	private Resource res;
	private C (Resource res){ this.res = res; }
	public Resource getResource(){ return res; }
}


class EnumTester{
	public static void main(String [] args){
		System.out.println(A.ALPHA.getResource());	
		System.out.println(B.BRAVO.getResource());	
		System.out.println(C.CHARLIE.getResource());
	}
}

When this code is run, an intuitive expectation is to see the following printed to the console:

BRAVO
CHARLIE
ALPHA

However, when I actually run the code we see:

BRAVO
CHARLIE
null

While this may seem a bit funky, the key is to understand what enum constants mean in Java. The key question to address is: “when is the constructor for an enumerated type invoked”. To answer this, it is helpful to remember that enum constants are implicitly public static final. Java guarantees that:

  • Static variables in a class are initialized before any object of that class can be created
  • Static variables in a class are initialized before any static method of the class runs

Knowing this, the behavior of the above code snippet becomes clearer. Here’s what happens in the main method:

  1. The fun happens at line 35, when we print   A.ALPHA.getResource(). Behind the scene, the class loader loads enumeration A into memory (i.e. initializes A).
  2. Once A is loaded into memory, the enum constant ALPHA gets created via call to the constructor where B.BRAVO is passed in as the argument.
  3. At this point, enumeration B is initialized and enum constant BRAVO gets created via a call to the constructor where C.CHARLIE is passed in as the argument.
  4. Same as before, now enumeration C is initialized (i.e. loaded into memory). Now here’s where things become interesting.
  5. Immediately after the initialization of C, we create the enum constant CHARLIE via a call to the constructor and pass in A.ALPHA as the argument. However, A.ALPHA has not been instantiated yet, and therefore enum constant CHARLIE gets null as the value of its resource instance variable. 

This means that once the statement A.ALPHA.getResource() is evaluated, A, B and C are all loaded into memory and all the corresponding enum constants have already been instantiated. Lines 35-37 simply then print the corresponding resources for each enum constant.

A Possible Solution

It is obvious that the entire problem stems from the cyclic dependency between A, B and C. Usually (but not always), this is an indication of a bad design choice and the fix is to simply get rid of the cyclic dependency. Assuming we want to keep the dependency, what are our options then?

Our solutions lies in Java's ability to allow instance-specific methods on enumerations. This is shown in the code below.

Running the following code with the EnumTester main method above will give us the results we wanted, without the problems caused by the previous approach.

enum A implements Resource{
	ALPHA { public Resource getResource() {return B.BRAVO; } };
	
	public abstract Resource getResource();
}

enum B implements Resource{
	BRAVO { public Resource getResource() { return C.CHARLIE; } };
	
	public abstract Resource getResource();
}

enum C implements Resource{
	CHARLIE { public Resource getResource() { return A.ALPHA; }};
	
	public abstract Resource getResource();
}

What do you think? Do you know of any other ways to resolve the cyclic dependency? Have you seen any other weirdness related to Java’s Enums?

4 Comments

Filed under Java, Programming