常量字符串替换

时间:2016-05-05 10:31:23

标签: java

我有一类常量

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>可以将值设为AB

2 个答案:

答案 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));
    }
}