在许多类中共享Java中的常量字符串?

Sharing constant strings in Java across many classes?

我希望在一个地方拥有Java常量字符串,并在整个项目(多个类)中使用它们。

实现这一目标的建议方法是什么?


1
public static final String CONSTANT_STRING="CONSTANT_STRING";

常量应为:

  • 公共-以便可以从任何地方访问
  • 静态-不需要创建实例
  • 最终-因为它的常量不应该被允许改变
  • 按照Java命名约定应该大写,以便在Java文档中易于阅读和突出。
  • 有些情况下,接口只是用来保存常量,尽管我看不出任何理由这样做,而且创建一个接口来保存常量也被认为是一种糟糕的做法,另一种方法是将它保存在更合理的类中。

    例如

    JFrame包含EXIT_ON_CLOSE,任何属于JFrame子类的类都可以访问它,并且在JFrame而不是JComponent中保存也是有意义的,因为并非所有组件都有关闭的选项。


    正如@mprabhat之前回答的那样,常量应该是publicstaticfinal,并用大写字母输入。

    将它们分组在一个类中有助于您:

  • 不需要知道所有的常量。许多IDE(如Eclipse)向您显示了类拥有的所有字段的列表。所以你只需按CTRL+SPACE,就可以知道你可以使用哪些常量。

  • 使它们在编译时具有类型安全性。如果你使用Strings,你可能会把"DATABASE_EXCEPTION""DATABSE_EXSCEPTION"拼错,只会在执行过程中注意到(如果你很幸运并注意到)。你也可以从自动完成中获益。

  • 帮助您在执行期间保存内存。对于常量的1个实例,您只需要内存。例如:(一个真实的例子)如果在代码中有1000次不同的类中的String数据库异常,那么它们中的每一个在内存中都将是不同的实例。

  • 您可能还有其他一些考虑:

  • 添加javadoc注释,这样使用常量的程序员就可以获得更多关于常量的语义信息。当您按CTRL+SPACE时,它显示为工具提示。即:

    1
    2
    3
    4
    /** Indicates an exception during data retrieving, not during connection. */
    public static final String DATABASE_EXCEPTION ="DATABASE_EXCEPTION";
    /** Indicates an exception during the connection to a database. */
    public static final String DATABASE_CONNECTION_EXCEPTION =" DATABASE_CONNECTION_EXCEPTION";
  • 向常量的标识符添加语义。如果你有一个常数"Y",有时意味着是和其他时间,那么考虑使用两个不同的常数。

    1
    2
    3
    public static final String Y ="Y"; // Bad
    public static final String YEAR ="Y";
    public static final String YES ="Y";

    如果将来决定更改常量的值,它将帮助您。

    1
    2
    3
    /** Year symbol, used for date formatters. */
    public static final String YEAR ="A"; // Year is A?o, in Spanish.
    public static final String YES ="S"; // Yes is Sí, in Spanish.
  • 在运行时之前,您可能不知道常量的值。你可以从配置文件中读取它们。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Constants
    {
      /** Message to be shown to the user if there's any SQL query problem. */
      public static final String DATABASE_EXCEPTION_MESSAGE; // Made with the 2 following ones.
      public static final String DATABASE_EXCEPTION ="DATABASE_EXCEPTION";
      public static final String MESSAGE ="MESSAGE";

      static {
        DATABASE_EXCEPTION_MESSAGE = DATABASE_EXCEPTION + MESSAGE; // It will be executed only once, during the class's [first] instantiation.
      }

    }

  • 如果你的常量类太大,或者你认为它将来会增长太多,你可以根据不同的含义(同样,语义)将它分成不同的类:ConstantDBConstantNetwork等。

  • 缺点:

  • 您团队的所有成员都必须使用相同的类,并为常量使用相同的命名法。在一个大型项目中,找到两个定义并不奇怪:

    1
    2
    public static final String DATABASE_EXCEPTION ="DATABASE_EXCEPTION";
    public static final String EXCEPTION_DATABASE ="DATABASE_EXCEPTION";

    将数百行或不同的常量类分隔开。甚至更糟:

    1
    2
    3
    4
    /** Indicates an exception during data retrieving, not during connection. */
    public static final String DATABASE_EXCEPTION ="DATABASE_EXCEPTION";
    /** Indicates an exception during data retrieving, not during connection. */
    public static final String EXCEPTION_DATABASE ="EXCEPTION_DATABASE";

    不同的标识符,对于不同的值,具有相同的含义(并用于相同的目的)。

  • 这可能会使可读性变差。做同样的事情需要写更多的东西:

    1
    if ("Y".equals(getOptionSelected()) {

    VS

    1
    if (ConstantsWebForm.YES.equals(getOptionSeleted()) {
  • 类中常量应该如何排序?按字母顺序?所有相关常量在一起?按照创建/需要的顺序排列?谁应该对订单的正确性负责?任何(足够大的)常量重新排序都将被视为版本控制系统中的一个混乱。

  • 嗯,时间比我想象的要长。欢迎任何帮助/批评。


    您应该创建一个存储所有常量的常量类。

    像projectnameconstants.java

    它包含所有静态常量字符串,您可以通过类名访问它。

    例如

    1
    2
    3
    classname :  MyAppConstants.java

    public static final String MY_CONST="my const string val";

    您可以访问它作为

    1
    MyAppConstants.MY_CONST


    最佳实践是使用JavaEnUM(Java 5之后)

    类方法的问题:

  • 不打字
  • 无名称空间
  • 脆性
  • 请检查Java文档。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public enum Constants {

        CONSTANT_STRING1("CONSTANT_VALUE1"),
        CONSTANT_STRING2("CONSTANT_VALUE2"),
        CONSTANT_STRING3("CONSTANT_VALUE3");

        private String constants;

        private Constants(String cons) {
            this.constants = cons;
        }
    }

    枚举可以用作常量。

    编辑:你可以叫这个Constants.CONSTANT_STRING1


    1
    2
    3
    public class SomeClass {
        public static final String MY_CONST ="Some Value";
    }

    如果它应该是纯常量类,那么也将构造函数设为私有。

    1
    2
    3
    4
    5
    6
    7
    public class Constants {
        public static final String CONST_1 ="Value 1";
        public static final int CONST_2 = 754;

        private Constants() {
        }
    }

    这样就不可能实例化这个类。


    在主包(即com.yourcompany)的基础上创建一个名为Constants的类,其中包含所有常量。同时将构造函数设为私有,这样就不会从此类创建任何对象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Constants {

        private Constants() {
            // No need to create Constants objects
        }

        public static final String CONSTANT_ONE ="VALUE_CONSTANT_ONE";
        public static final String CONSTANT_TWO ="VALUE_CONSTANT_TWO";
    }


    您应该将常量分解成它们所属的组,比如它们将被最多使用的位置,并将它们定义为这些类中的公共静态final。在您进行下去的过程中,似乎有定义常量的接口是合适的,但是不要急于创建一个包含所有常量的单片接口。只是设计不好。


    我想你要找的正确答案是

    1
    import static com.package.YourConstantsClass.*;


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public enum Constants {

    CONSTANT_STRING1("CONSTANT_VALUE1"),
    CONSTANT_STRING2("CONSTANT_VALUE2"),
    CONSTANT_STRING3("CONSTANT_VALUE3");

    private String constants;

    private Constants(String cons) {
        this.constants = cons;
    }
        @JsonValue
    @Override
    public String toString() {
        return constants;
    }

    }

    使用IT常量。常量_string1.tostring()。


    创建一个公共的class,并为每个常量字符串创建一个这样的字段

    public static final String variableName ="string value";