61

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

实现这一目标的推荐方法是什么?

4

10 回答 10

55
public static final String CONSTANT_STRING="CONSTANT_STRING";

常量应该是:

  1. public - 以便可以从任何地方访问它
  2. 静态 - 无需创建实例
  3. final - 因为它的常量不应该被允许改变
  4. 根据 Java 命名约定,应该大写以便易于阅读并在 Java 文档中脱颖而出。

在某些情况下,接口仅用于保留常量,但这被认为是一种不好的做法,因为接口应该定义类型的行为。

更好的方法是将其保留在更有意义的类中。

例如

JFrame具有EXIT_ON_CLOSEcontant,任​​何子类都可以访问它的类,并且保留而不JFrame保留也是有意义的,因为并非所有组件都可以选择关闭。JFrameJComponent

于 2012-06-05T11:03:18.000 回答
26

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

将它们分组到一个班级可以帮助您:

  1. 不需要知道你拥有的所有常量。许多 IDE(如 Eclipse)会向您显示一个类所具有的所有字段的列表。因此,您只需按下CTRL+SPACE并了解您可以使用哪些常量。

  2. 在编译时使它们类型安全。如果你使用了Strings,你可能会拼错"DATABASE_EXCEPTION""DATABSE_EXSCEPTION"并且只在执行期间注意(如果你很幸运并且注意到它)。您还可以从自动完成中获利。

  3. 帮助您在执行过程中节省内存。您只需要 1 个常量实例的内存。IE:(一个真实的例子)如果您String在代码中的不同类中有 1000 次“DATABASE_EXCEPTION”,那么它们中的每一个都将是内存中的不同实例。

您可能还有其他一些注意事项:

  1. 添加 javadoc 注释,让使用常量的程序员可以获得更多关于常量的语义信息。当您按下 时,它会显示为工具提示CTRL+SPACE。IE:

    /** 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";
    
  2. 为常量的标识符添加语义。如果您有常数"Y",有时表示yes而其他时间表示year,请考虑使用 2 个不同的常数。

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

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

    /** 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.
    
  3. 您可能直到运行时才知道常量的值。IE:您可以从配置文件中读取它们。

    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.
      }
    

    }

  4. 如果您的常量类太大,或者您认为它将来会增长太多,您可以将它划分为不同的类以获得不同的含义(再次,语义):ConstantDB、、ConstantNetwork等等。

缺点:

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

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

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

    /** 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"; 
    

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

  2. 它可能会使可读性更差。为了做同样的事情,不得不写更多:

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

    对比

    if (ConstantsWebForm.YES.equals(getOptionSeleted()) {
    
  3. 类中的常量应该如何排序?按字母顺序?所有相关的常量在一起?为了创建/需要它们?谁应该对命令的正确性负责?任何(足够大的)常量重新排序都将被视为版本控制系统中的一团糟。

嗯,这比我预期的要长。欢迎任何帮助/批评。

于 2012-09-06T11:54:46.640 回答
19

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

像 ProjectNameConstants.java

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

例如

classname :  MyAppConstants.java

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

你可以访问它

MyAppConstants.MY_CONST
于 2012-06-05T11:02:54.157 回答
7

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

类方法的问题:

  1. 不是类型安全的
  2. 没有命名空间
  3. 脆性

请检查 java 文档。

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

于 2012-06-05T11:52:57.147 回答
3
public class SomeClass {
    public static final String MY_CONST = "Some Value";
}

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

public class Constants {
    public static final String CONST_1 = "Value 1";
    public static final int CONST_2 = 754;

    private Constants() {
    }
}

那么就不可能实例化这个类。

于 2012-06-05T11:04:20.380 回答
3

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

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";
}
于 2012-06-05T11:16:48.027 回答
2

您应该将常量分解为它们所属的组,例如最常使用它们的组,并将它们定义为这些类中的 public static final 。随着您的进行,拥有定义常量的接口似乎是合适的,但要抵制创建一个包含所有常量的单一接口的冲动。这不是好的设计。

于 2012-06-05T11:11:55.803 回答
1

我想你正在寻找的正确答案是

import static com.package.YourConstantsClass.*;
于 2018-05-29T02:50:01.150 回答
0

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

public static final String variableName = "string value";

于 2012-06-05T11:03:56.177 回答
0
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;
}

}

使用它 Constants.CONSTANT_STRING1.toString()

于 2017-06-29T15:17:12.977 回答