我希望在一个地方拥有Java常量字符串,并在整个项目(多个类)中使用它们。
实现这一目标的建议方法是什么?
- 静态类的静态方法返回常量字符串怎么样?
- 这不是推荐的Java设计方法。将常量放在它们相关的类中。
- @Beerbajay但是我需要在一些类中使用这些字符串,推荐使用什么方法?
- @如果按照比尔巴杰的建议,你仍然可以在不同的班级使用它们。只需使字段静态、公开和最终。
- 这取决于您的具体用例。通常这些信息有一个逻辑"主"位置,所以您将常量放在那里,然后从其他需要信息的地方引用该类和常量(例如MyClass.MY_CONSTANT)。如果你发现自己需要一个"常量类",这通常是一个没有充分考虑通过设计的迹象。
- 它对性能的影响会更好吗?还是更糟?
1
| public static final String CONSTANT_STRING ="CONSTANT_STRING"; |
常量应为:
公共-以便可以从任何地方访问
静态-不需要创建实例
最终-因为它的常量不应该被允许改变
按照Java命名约定应该大写,以便在Java文档中易于阅读和突出。
有些情况下,接口只是用来保存常量,尽管我看不出任何理由这样做,而且创建一个接口来保存常量也被认为是一种糟糕的做法,另一种方法是将它保存在更合理的类中。
例如
JFrame包含EXIT_ON_CLOSE,任何属于JFrame子类的类都可以访问它,并且在JFrame而不是JComponent中保存也是有意义的,因为并非所有组件都有关闭的选项。
- +一个好答案。尽管如此,使用接口被认为是不好的做法,应该提到
- @吉米:为什么使用接口是一个坏习惯??
- 接口是收缩的,使用它们来保存常量是没有意义的
- @使用界面并不坏,但使用界面保存常量是:)请阅读此链接以获得更详细的解释:stackoverflow.com/questions/320588/…
- 如果一个接口或包含常量的类应用于包中的所有类,而不是特定的任何类,那么让它们成为包含常量的接口或类仍然是一个坏做法吗?例如,日志消息前缀字符串。
正如@mprabhat之前回答的那样,常量应该是public、static、final,并用大写字母输入。
将它们分组在一个类中有助于您:
不需要知道所有的常量。许多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.
} |
}
如果你的常量类太大,或者你认为它将来会增长太多,你可以根据不同的含义(同样,语义)将它分成不同的类:ConstantDB、ConstantNetwork等。
缺点:
您团队的所有成员都必须使用相同的类,并为常量使用相同的命名法。在一个大型项目中,找到两个定义并不奇怪:
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()) { |
类中常量应该如何排序?按字母顺序?所有相关常量在一起?按照创建/需要的顺序排列?谁应该对订单的正确性负责?任何(足够大的)常量重新排序都将被视为版本控制系统中的一个混乱。
嗯,时间比我想象的要长。欢迎任何帮助/批评。
- 好极了,谢谢。
- 谢谢你的支持。
- 感谢您提供详细信息!+ 1
您应该创建一个存储所有常量的常量类。
像projectnameconstants.java
它包含所有静态常量字符串,您可以通过类名访问它。
例如
1 2 3
| classname : MyAppConstants. java
public static final String MY_CONST ="my const string val"; |
您可以访问它作为
- 或者将其定义为负责此字符串的对象中的"公共静态最终字符串"
- 你为什么要这样做?我的直觉告诉我这是一个可怕的想法,但我很高兴被证明是相反的。
- @布鲁诺最好将所有相关常量保存在同一个文件中。像所有与一个模块相关的SQL查询常量一样应该在一个Java常量中。
- 将常量与其类放在一起。不要只为常量创建单独的类。SQL查询常量应该与DAO类等一起使用。这方面的例外情况可能是一个枚举类,用于所有相同"thing"的字符串(行星名称是典型的例子)。
最佳实践是使用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。
- 这些问题(类型化、命名空间和脆性)与旧的EnUM方法(作为Java 5之前的模式)一起发生。见JavaDoc的enums。
- 调用它的方法不是Constants.CONSTANT_STRING1,因为它返回的是Constants类型的内容。你得称它为Constants.CONSTANT_STRING1.toString()或Constants.CONSTANT_STRING1.name()。
- 正如J.A.I.L.所评论的,您当前的代码示例不起作用。您的调用返回一个Constants类型的对象,而不是问题中所需的String类型的对象。
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 () {
}
} |
这样就不可能实例化这个类。
- 最好让它成为static,当Java中有更好的选项时,你不应该使用这个"私有构造函数"方法。
- @Ryuji你完全错了,你把它和C混在一起了。请看下面的示例:stackoverflow.com/a/7486111/1350762
在主包(即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";