Static Fields in Enums
Enums in Java have a numeric, read-only, property called
Sometimes, however, it is necessary to associate to an Enum another numeric property, let's call it
It seems totally trivial to write an Enum that has a static map from codes to Enum instances:
Note the method
Unfortunately, this will not compile. The compiler reports that it is illegal to access the static member
This makes sense when one imagines how an Enum is first translated into a class by the compiler. Roughly, there is a static initializer that creates the
See http://java.sun.com/docs/books/jls/third_edition/html/classes.html#301020 for further details.
Fortunately, there is an easy workaround: it's enough to use a different class to store the map from codes to Enum instances, and a private static inner class does the job:
ordinal
that is a strictly consecutive integer (starting from 0).Sometimes, however, it is necessary to associate to an Enum another numeric property, let's call it
code
, that it may not be strictly consecutive and normally specifies something different than a sequence number. Furthermore, it may be necessary to be able to lookup the correct Enum from its code
.It seems totally trivial to write an Enum that has a static map from codes to Enum instances:
public enum Port
{
SSH(22), TELNET(23), HTTP(80), POP3(110), HTTPS(443);
// The static map from codes to Enum instances
private static final
Map<Integer, Port> ports = new HashMap<Integer, Port>();
private final int code;
private Port(int code)
{
this.code = code;
ports.put(code, this);
}
public int getCode()
{
return this.code;
}
// Lookup method that returns the Enum instance from the given code
public static Port from(int code)
{
return ports.get(code);
}
}
Note the method
static from(int code)
that returns an Enum instance from the given code
.Unfortunately, this will not compile. The compiler reports that it is illegal to access the static member
ports
from the constructor.This makes sense when one imagines how an Enum is first translated into a class by the compiler. Roughly, there is a static initializer that creates the
Ports
instances, in this case SSH, TELNET, etc.; this static initializer is the first initializer run when the Ports
class is referenced, and it is easy to see that when the static initializer runs, no other initializers have been run yet, and in particular the static Map ports
has not been created yet.See http://java.sun.com/docs/books/jls/third_edition/html/classes.html#301020 for further details.
Fortunately, there is an easy workaround: it's enough to use a different class to store the map from codes to Enum instances, and a private static inner class does the job:
public enum Port
{
SSH(22), TELNET(23), HTTP(80), POP3(110), HTTPS(443);
private final int code;
private Port(int code)
{
this.code = code;
Ports.ports.put(code, this);
}
public int getCode()
{
return this.code;
}
// Lookup method that returns the Enum instance from the given code
public static Port from(int code)
{
return Ports.ports.get(code);
}
private static class Ports
{
// The static map from codes to Enum instances
private static final
Map<Integer, Port> ports = new HashMap<Integer, Port>();
}
}