我有一类常量
public class Constants {
private static final String A = "1";
private static final String B = "2";
}
我有另一个类,它将常量的名称作为函数参数并调用常量。
public class SomeClas {
void someMethod(String constantName) {
callSomeOtherMethod(Constants.<constantName>)
}
}
我该怎么做?我的<constantName>
可以将值设为A
或B
。
答案 0 :(得分:2)
假设你无法改变课程的方式,你就会有反思。使用反射执行此操作的代码如下:
void someMethod(String constantName) throws NoSuchFieldException, IllegalAccessException {
Field fd = Constants.class.getDeclaredField(constantName);
fd.setAccessible(true);
String val = (String) fd.get(null);
callSomeOtherMethod(val);
}
答案 1 :(得分:0)
答案取决于您对班级Constants
的控制程度。如果这是你无法控制的,你无法改变它,那么反射就是你要走的路。 (见marcinj&#39; s answer)
但是,如果您完全控制Constants
,那么我会考虑重构为enum
(自Java 5起可用)。这是否值得,将取决于此类在您的代码库中的嵌入方式。引用Constants
的地方必须改变多少?这是其他应用程序使用的共享类吗?可能这里的重构太麻烦了,只有你可以决定。
为了帮助您确定,这里总结了为什么使用枚举通常被认为是更好的原因,当然对于新的开发。如果你决定不进行重构,那么下次你需要创建这样的新常量时,还是值得一看。
反对使用反思的原因
更喜欢enum到String / int常量的原因
- 每个常量都可以有属性和方法 - 使用Joshua Bloch示例,您可能有一个常量类列出太阳系的行星。如果使用枚举类型,则可以添加质量,半径等属性以及检索它们的方法
- 编译时间类型安全性 - 如果要将此类型传递给方法,则使用一类String常量,类型将为String,而不是Constants。这意味着编译器会对您传入的任何旧String感到满意,无论它是否为常量。如果您使用枚举,则您具有编译器可以检查的正确类型
- 你可以免费获得很多,例如name(),valueOf(),实现Serializable,Comparable等。这意味着你不必重新发明轮子。
- 这是一个深思熟虑的设计 - 在枚举之前,有许多设计模式可以通过不同的考虑因素实现相同的目标。例如,您是否担心线程安全?还是序列化?如果你使用枚举,你不必担心这一点。
代码示例
如果你决定重构枚举,那么这里有一个示例代码片段来说明如何实现这一点。
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;
}
}
您现在可以通过A,B名称或&#34; 1&#34;,&#34; 2&#34;来查找常量值。值。 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));
}
}