fun with enums
i stumbled upon a very nasty corner-case using enums. i wont call it a puzzler, but you may want to try to predict the output of the following:
| Java | | copy | | ? |
public enum Person { |
PETER, PAUL, MARY; |
private Food favFood; |
Food getFavFood() |
{ |
return this.favFood; |
} |
static void setPreference(final Person p, final Food f) |
{ |
p.favFood = f; |
} |
public static void main(final String[] args) |
{ |
final Person[] people = Person.values(); |
for (int i = 0; i < people.length; i++) |
{ |
final Person p = people[i]; |
System.out.println(p.name() + " likes " + p.getFavFood()); |
} |
} |
} |
enum Food { |
SOUP, MEAT, VEGETABLE; |
static |
{ |
Person.setPreference(Person.MARY, SOUP); |
Person.setPreference(Person.PETER, Food.VEGETABLE); |
} |
} |
in order to not spoil your fun, i put the output in the comments, so that you have to click on it…
so, if you´re clever enough to spot the problem, we can take it a little further by adding
| Java | | copy | | ? |
static |
{ |
System.out.println(Food.SOUP); |
} |
to the class person and rerun it. isn´t that nice !?
i have - let´s just say 'a clue' - what is going on, but proper explainations are pretty welcome
disclaimer: (JDK1.6, eclipse compiler, standard settings) ... no compiler was hurt in the process


Output of code above:
PETER likes null
PAUL likes null
MARY likes null
with
static { System.out.println(Food.SOUP); }added:SOUP
PETER likes VEGETABLE
PAUL likes null
MARY likes SOUP
Nice one.
It seems that java ignores the class Food in Person as long as it is null.
Perhaps the class loader only checks for existence of class Food and does not initialize the class.
With System.out.println(Food.SOUP) you enforce the class loading and initialization.
hmm. from my understanding, loading of the class, thus initialization of the enum is supposed to be guaranteed before use.
reason for the fun is the circular dependency in the static initialization of the enums. the classloader has to decide for one to be first. that point in time, the other is not yet initialized, thus cannot be referenced, so the references used in the first are pointing to null.
adding the static sysout changes the order, and so makes it work
Thanks to Martin for the Links:
http://www.saager.org/tag/static+initializer
http://onjava.com/pub/a/onjava/2004/09/15/statics.html
and of course
http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#44557
so my ‘clue’ was right.