This is a variation of the perpertual "lengthy-if or switch" dilemma...
Consider a multithreaded application using a static method that contains a long (over a dozen conditions) if
statement, which checks the type of an object and returns a value accordingly, i.e. something like
public static String checkType(Class<?> type)
{
if (type == A.class)
{
return aString;
}
else if (type == B.class)
{
return bString;
}
...
else if (type == z.class)
{
return zString;
}
}
Obviously a switch statement is not directly applicable here, so a common pattern is to have an enum
and call its valueOf()
, i.e. do something like
public enum Strings
{
A(aString), B(bString), ..., Z(zString)
private final String value;
private Strings(String value)
{
this.value = value;
}
public String value()
{
return this.value;
}
}
So, checkType()
could be re-written as
public static String checkType(Class<?> type)
{
return Strings.valueOf(getActualTypeName(type.getClass().getName())).value();
}
with appropriate checks for null
values added in production code and some String processing for non-primitive types, inside the getActualTypeName()
method, to retrieve the actual type name from strings like "class java.lang.Long"
(for primitives, the getName()
method returns the expected string, e.g. "long"
).
However, if valueOf()
is not thread-safe, this will not work in a concurrent environment. The same applies to using a (normal) Map
object and probably these two alternatives are variants of the same pattern, since enum.valueOf()
is apparently based on
Enum.valueOf(Class<T> enumType, String name)
which calls
enumType.enumConstantDirectory().get(name);
in the Class.java
class.
The enumConstantDirectory()
method, every time invoked, returns a new HashMap
, created from a copy of the values()
array.
Would that be thread safe?