A Switch on String Idiom for Java
There is no way to perform a true switch on a String in Java. This seemingly trivial bit of
functionality is common to many other languages, but has been frustratingly absent (to some) from Java. Various
techniques have been offered that involve hashing, Maps, etc., but they are all overly complicated and generally
not worth the trouble. With the advent of JDK 5.0 and its implementation of enum
, a reasonably close
approximation of this can be done using the following idiom. Create an enum using the default integer-based
mapping, e.g.:
public enum Day
{
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY;
}
Given this enum, the following switch statement could be used:
switch (Day.valueOf(str))
{
case SATURDAY:
case SUNDAY:
// weekend processing ...
break;
default:
// weekday processing ...
}
Enum.valueOf() matches the given String to the actual enum name using the same basic hashcode() matching technique that earlier proposals have suggested; but with this idiom, all of that machinery is generated by the compiler and Enum implementation. The set of possible String values is also maintained in a more structured way when held in an enum.
Of course, the above suffers from the serious drawback that Enum.valueof() can throw an unchecked IllegalArgumentException or NullPointerException. The only real way to get around this issue is to create a new static method that absorbs these Exceptions and instead returns some default value:
public enum Day
{
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY,
NOVALUE;
public static Day toDay(String str)
{
try {
return valueOf(str);
}
catch (Exception ex) {
return NOVALUE;
}
}
}
Then the switch
can be written to include a default
clause that handles unexpected
String values:
switch (Day.toDay(str))
{
case SUNDAY:
case MONDAY:
case TUESDAY:
// etc ...
default:
// any non-Day value
}
While not quite as compact as the first technique, this is more robust and offers the possibility of performing
case-insensitive switching also by calling, for example, toUpperCase() in the convert method after first checking
the passed-in String for null
.
This was exactly the efficient solution I needed. Much thanks.
» Posted by Jake on March 8, 2007 11:06 PM