Reputation: 1925
I have a class of constants
public class Constants {
private static final String A = "1";
private static final String B = "2";
}
I have another class which takes in the name of the constant as a function parameter and calls the constant.
public class SomeClas {
void someMethod(String constantName) {
callSomeOtherMethod(Constants.<constantName>)
}
}
How Do i do this? My <constantName>
can take values as A
or B
.
Upvotes: 2
Views: 325
Reputation: 7141
The answer depends on how much control you have of the class Constants
. If this is out of your control and you cannot change it then reflection is the way to go. (see marcinj's answer)
However, if you have full control over Constants
then I would consider refactoring to an enum
(available since Java 5). Whether this is worthwhile will depend on how embedded this class is in your code base. How many places that reference Constants
would have to change? Is this a shared class used by other applications? It could be that refactoring here is too much hassle, only you can decide.
To help you decide here is a summary of reasons why using an enum would generally be considered preferable, certainly for new development. If you decide not to refactor then it's still worth a look for the next time you need to create new constants like this.
Reasons against using reflection
Reasons to prefer an enum to String/int constants
- Each constant can have attributes and methods - Using the Joshua Bloch example you might have a constants class listing the planets of the solar system. If you use an enum type then you can add attributes such as mass, radius etc and methods to retrieve them.
- Compile time type safety - With a class of String constants if you want to pass this in to a method the type will be String, not Constants. This means the compiler will be happy with any old String you pass in whether it's a Constant or not. If you use an enum you have a proper type that the compiler can check.
- You get lots for free such as name(), valueOf(), implements Serializable, Comparable etc. This means you don't have to re-invent the wheel.
- It's a thought out design - Before enums there were a number of design patterns to achieve the same thing with varying levels of considerations. For example do you worry about thread safety? Or Serialization? If you use an enum you don't have to worry about this.
Code example
If you do decide to refactor to an enum then here is an example code snippet to show how this might be achieved.
public enum Constant
{
A("1"),
B("2");
private String value;
private Constant(String value)
{
this.value = value;
}
public Constant lookupConstantByValue(String value)
{
for(Constant constant : values())
{
if(constant.value.equals(value))
{
return constant;
}
}
return null;
}
}
You could now lookup constant values either by the A,B name or the "1", "2" value. e.g.
public class SomeClas
{
void someMethod(String constantName)
{
// if constantName is 1 or 2
callSomeOtherMethod(Constant.lookupConstantByValue(constantName));
// if constantName is A or B
callSomeOtherMethod(Constant.valueOf(constantName));
}
}
Upvotes: 0
Reputation: 49986
Assuming you cannot change anything in the way your classes look like, you are left with reflection. The code to do it with reflection is as follows:
void someMethod(String constantName) throws NoSuchFieldException, IllegalAccessException {
Field fd = Constants.class.getDeclaredField(constantName);
fd.setAccessible(true);
String val = (String) fd.get(null);
callSomeOtherMethod(val);
}
Upvotes: 2