简体   繁体   English

常量字符串替换

[英]Constant string substitution

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 .我的<constantName>可以将值作为AB

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

The answer depends on how much control you have of the class Constants .答案取决于您对类Constants If this is out of your control and you cannot change it then reflection is the way to go.如果这超出了您的控制范围并且您无法更改它,那么反思就是要走的路。 (see marcinj's answer ) (见 marcinj 的回答

However, if you have full control over Constants then I would consider refactoring to an enum (available since Java 5).但是,如果您可以完全控制Constants那么我会考虑重构为enum (自 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?有多少引用Constants地方必须改变? 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反对使用反射的原因

  • Performance - runtime reflection is much slower than compiled method calls or attribute lookups.性能- 运行时反射比编译的方法调用或属性查找慢得多。 If your code is called infrequently then you probably won't notice it but if this is a utility method that is called many times then it could be a potential bottleneck.如果您的代码很少被调用,那么您可能不会注意到它,但如果这是一个被多次调用的实用方法,那么它可能是一个潜在的瓶颈。
  • Overriding the access modifier - private scope attributes are supposed to only be accessible from within the same class.覆盖访问修饰符- 私有范围属性应该只能从同一个类中访问。 By overriding this you can introduce problems when refactoring as your reflection code could be dependent on attributes or methods that it shouldn't know about.通过覆盖它,您可以在重构时引入问题,因为您的反射代码可能依赖于它不应该知道的属性或方法。
  • Compile time safety - if you call a method or reference an attribute in the standard way the compiler will check it exists.编译时安全- 如果您以标准方式调用方法或引用属性,编译器将检查它是否存在。 If you look things up with reflection then you leave yourself open to runtime errors.如果您使用反射进行查找,那么您将面临运行时错误。

Reasons to prefer an enum to String/int constants比 String/int 常量更喜欢 enum 的原因
- 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. -每个常量都可以有属性和方法- 使用 Joshua Bloch 示例,您可能有一个常量类,列出了太阳系的行星。 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. -您可以免费获得很多东西,例如 name()、valueOf()、实现 Serializable、Comparable 等。这意味着您不必重新发明轮子。
- 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.您现在可以通过 A、B 名称或“1”、“2”值查找常量值。 eg例如

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