繁体   English   中英

常量字符串替换

[英]Constant string substitution

我有一类常量

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

假设你不能改变你的类的任何东西,你就剩下反思了。 用反射来做的代码如下:

void someMethod(String constantName) throws NoSuchFieldException, IllegalAccessException {
    Field fd = Constants.class.getDeclaredField(constantName);
    fd.setAccessible(true);
    String val = (String) fd.get(null);
    callSomeOtherMethod(val);
}

答案取决于您对类Constants 如果这超出了您的控制范围并且您无法更改它,那么反思就是要走的路。 (见 marcinj 的回答

但是,如果您可以完全控制Constants那么我会考虑重构为enum (自 Java 5 起可用)。 这是否值得取决于此类在您的代码库中的嵌入程度。 有多少引用Constants地方必须改变? 这是其他应用程序使用的共享类吗? 可能是这里的重构太麻烦了,只有你能决定。

为了帮助您做出决定,这里总结了为什么使用枚举通常被认为更可取的原因,当然对于新的开发。 如果您决定不重构,那么下次您需要像这样创建新常量时仍然值得一看。

反对使用反射的原因

  • 性能- 运行时反射比编译的方法调用或属性查找慢得多。 如果您的代码很少被调用,那么您可能不会注意到它,但如果这是一个被多次调用的实用方法,那么它可能是一个潜在的瓶颈。
  • 覆盖访问修饰符- 私有范围属性应该只能从同一个类中访问。 通过覆盖它,您可以在重构时引入问题,因为您的反射代码可能依赖于它不应该知道的属性或方法。
  • 编译时安全- 如果您以标准方式调用方法或引用属性,编译器将检查它是否存在。 如果您使用反射进行查找,那么您将面临运行时错误。

比 String/int 常量更喜欢 enum 的原因
-每个常量都可以有属性和方法- 使用 Joshua Bloch 示例,您可能有一个常量类,列出了太阳系的行星。 如果您使用枚举类型,那么您可以添加质量、半径等属性以及检索它们的方法。
-编译时类型安全- 使用一类字符串常量,如果要将其传递给方法,则类型将是字符串,而不是常量。 这意味着编译器会对您传入的任何旧字符串感到满意,无论它是否为常量。 如果您使用枚举,则您具有编译器可以检查的正确类型。
-您可以免费获得很多东西,例如 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 名称或“1”、“2”值查找常量值。 例如

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM