我看过类似这样的例子:
public class MaxSeconds {
public static final int MAX_SECONDS = 25;
}
我想我可以创建一个常量类来包装常量,将它们声明为静态常量。我几乎不懂Java,想知道这是否是创建常量的最佳方式。
那是完全可以接受的,甚至可能是标准。
(public/private) static final TYPE NAME = VALUE;
其中TYPE
表示类型,NAME
表示大写字母和下划线代替空格的名称,VALUE
表示常量值。
我强烈建议不要将常量放在它们自己的类或接口中。
另外注意:声明为final但可变的变量仍然可以更改;但是,该变量永远不会指向不同的对象。
例如:
public static final Point ORIGIN = new Point(0,0);
public static void main(String[] args){
ORIGIN.x = 3;
}
这是合法的,ORIGIN
将成为点 (3, 0)。
我强烈建议不要使用单个常量类。虽然在当时可能看起来是一个好主意,但当开发人员拒绝记录常量并且该类涵盖了超过500个与应用程序完全不相关的常量时,通常会导致常量文件变得完全无法阅读。而应该:
使用接口仅用于保存常量是一种糟糕的实践(由Josh Bloch命名为常量接口模式)。以下是Josh的建议:
如果常量与现有类或接口密切相关,则应将其添加到该类或接口中。例如,所有装箱数值原始类(如Integer和Double)都导出MIN_VALUE和MAX_VALUE常量。如果常量最好被视为枚举类型的成员,则应将它们用enum类型导出。否则,您应该使用不可实例化的实用程序类导出这些常量。
示例:
// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
private PhysicalConstants() { } // Prevents instantiation
public static final double AVOGADROS_NUMBER = 6.02214199e23;
public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
public static final double ELECTRON_MASS = 9.10938188e-31;
}
关于命名规范:
按照约定,这些字段的名称由大写字母组成,单词之间用下划线分隔。关键是这些字段包含原始值或者不可变对象的引用。
abstract
而不是私有构造函数并不能完全阻止实例化,因为可以对其进行子类化并实例化子类(虽然这不是一个好主意,但是可能会发生)。您不能对具有私有构造函数的类进行子类化(至少没有通过非常恶劣的黑客手段),因为子类的构造函数需要调用其超类的(现在是私有的)构造函数。因此,将其标记为 final
是不必要的(但可能更加明确)。 - import this在《Effective Java》(第二版)中,建议您使用枚举而不是静态整数来表示常量。
这里有一篇关于Java中枚举的好文章: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
请注意,在该文章末尾提出了一个问题:
那么什么时候应该使用枚举?
答案是:
任何时候需要一个固定的常量集合时
避免使用接口:
public interface MyConstants {
String CONSTANT_ONE = "foo";
}
public class NeddsConstant implements MyConstants {
}
这很诱人,但违反了封装原则,模糊了类定义的区别。
我使用以下方法:
public final class Constants {
public final class File {
public static final int MIN_ROWS = 1;
public static final int MAX_ROWS = 1000;
private File() {}
}
public final class DB {
public static final String name = "oups";
public final class Connection {
public static final String URL = "jdbc:tra-ta-ta";
public static final String USER = "testUser";
public static final String PASSWORD = "testPassword";
private Connection() {}
}
private DB() {}
}
private Constants() {}
}
例如,我使用 Constants.DB.Connection.URL
来获取常量。 这样对我来说更具有“面向对象”的特点。
将静态final常量创建在单独的类中可能会引起麻烦。Java编译器实际上会优化这个过程,并将常量的实际值放入任何引用它的类中。
如果随后更改了“Constants”类并且您没有对引用该类的其他类进行硬重编译,则会出现新旧值组合使用的情况。
不要把它们看作常量,而是把它们看作配置参数并创建一个类来管理它们。让这些值不是最终的,甚至可以考虑使用getter方法。在未来,当您确定其中一些参数实际上应由用户或管理员配置时,这将更容易实现。
你可能犯的头号错误是创建一个名为Constants等泛称的全局可访问类,它会被垃圾填满,你将失去发现系统中使用这些常量的能力。
相反,常量应该放在“拥有”它们的类中。你有一个叫TIMEOUT的常量吗?它应该放在你的Communications()或Connection()类中。MAX_BAD_LOGINS_PER_HOUR呢?应该放在User()类中。等等。
另一个可能的用途是Java .properties文件,当“常量”可以在运行时定义,但不易于用户更改。你可以将它们打包到你的.jar文件中,并使用Class resourceLoader引用它们。
这是正确的方法。
通常情况下,常量不会被保存在单独的“常量”类中,因为它们不易被发现。如果常量与当前类有关,则将其保留在该类中可以帮助下一个开发人员。