在 Java 中实现常量的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/66066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to implement constants in Java?
提问by mk.
I've seen examples like this:
我见过这样的例子:
public class MaxSeconds {
public static final int MAX_SECONDS = 25;
}
and supposed that I could have a Constants class to wrap constants in, declaring them static final. I know practically no Java at all and am wondering if this is the best way to create constants.
并假设我可以有一个 Constants 类来包装常量,将它们声明为 static final。我几乎不知道 Java 并且想知道这是否是创建常量的最佳方式。
采纳答案by jjnguy
That is perfectly acceptable, probably even the standard.
这是完全可以接受的,甚至可能是标准。
(public/private) static final TYPE NAME = VALUE;
where TYPE
is the type, NAME
is the name in all caps with underscores for spaces, and VALUE
is the constant value;
其中TYPE
是类型,NAME
是所有大写的名称,空格下划线,VALUE
是常量值;
I highly recommend NOT putting your constants in their own classes or interfaces.
我强烈建议不要将常量放在它们自己的类或接口中。
As a side note: Variables that are declared final and are mutable can still be changed; however, the variable can never point at a different object.
附带说明:声明为 final 且可变的变量仍然可以更改;但是,变量永远不能指向不同的对象。
For example:
例如:
public static final Point ORIGIN = new Point(0,0);
public static void main(String[] args){
ORIGIN.x = 3;
}
That is legal and ORIGIN
would then be a point at (3, 0).
这是合法的,ORIGIN
然后将是 (3, 0) 处的一个点。
回答by Joel Martinez
I wouldn't call the class the same (aside from casing) as the constant ... I would have at a minimum one class of "Settings", or "Values", or "Constants", where all the constants would live. If I have a large number of them, I'd group them up in logical constant classes (UserSettings, AppSettings, etc.)
我不会将类称为与常量相同的类(除了大小写)......我至少会有一类“设置”、“值”或“常量”,所有常量都将存在于其中。如果我有大量它们,我会将它们分组到逻辑常量类(UserSettings、AppSettings 等)中
回答by Jason Cohen
That's the right way to go.
这是正确的方法。
Generally constants are notkept in separate "Constants" classes because they're not discoverable. If the constant is relevant to the current class, keeping them there helps the next developer.
通常常量不会保存在单独的“常量”类中,因为它们是不可发现的。如果常量与当前类相关,将它们保留在那里有助于下一个开发人员。
回答by Jason Cohen
Just avoid using an interface:
只是避免使用接口:
public interface MyConstants {
String CONSTANT_ONE = "foo";
}
public class NeddsConstant implements MyConstants {
}
It is tempting, but violates encapsulation and blurs the distinction of class definitions.
它很诱人,但违反了封装并模糊了类定义的区别。
回答by Andrew Harmel-Law
To take it a step further, you can place globally used constants in an interface so they can be used system wide. E.g.
更进一步,您可以将全局使用的常量放在接口中,以便它们可以在系统范围内使用。例如
public interface MyGlobalConstants {
public static final int TIMEOUT_IN_SECS = 25;
}
But don't then implement it. Just refer to them directly in code via the fully qualified classname.
但是不要执行它。只需通过完全限定的类名直接在代码中引用它们。
回答by Sébastien D.
What about an enumeration?
枚举呢?
回答by MetroidFan2002
I would highly advise against having a single constants class. It may seem a good idea at the time, but when developers refuse to document constants and the class grows to encompass upwards of 500 constants which are all not related to each other at all (being related to entirely different aspects of the application), this generally turns into the constants file being completely unreadable. Instead:
我强烈建议不要使用单个常量类。这在当时看起来似乎是个好主意,但是当开发人员拒绝记录常量并且类增长到包含 500 个以上的常量时,这些常量彼此根本不相关(与应用程序的完全不同的方面相关),这通常变成完全不可读的常量文件。反而:
- If you have access to Java 5+, use enums to define your specific constants for an application area. All parts of the application area should refer to enums, not constant values, for these constants. You may declare an enum similar to how you declare a class. Enums are perhaps the most (and, arguably, only) useful feature of Java 5+.
- If you have constants that are only valid to a particular class or one of its subclasses, declare them as either protected or public and place them on the top class in the hierarchy. This way, the subclasses can access these constant values (and if other classes access them via public, the constants aren't only valid to a particular class...which means that the external classes using this constant may be too tightly coupled to the class containing the constant)
- If you have an interface with behavior defined, but returned values or argument values should be particular, it is perfectly acceptible to define constants on that interface so that other implementors will have access to them. However, avoid creating an interface just to hold constants: it can become just as bad as a class created just to hold constants.
- 如果您有权使用 Java 5+,请使用枚举为应用程序区域定义特定的常量。对于这些常量,应用程序区域的所有部分都应该引用枚举,而不是常量值。您可以像声明类一样声明一个枚举。枚举可能是 Java 5+ 中最(并且可以说是唯一)有用的特性。
- 如果您有仅对特定类或其子类之一有效的常量,请将它们声明为 protected 或 public 并将它们放在层次结构中的顶级类。这样,子类就可以访问这些常量值(如果其他类通过 public 访问它们,这些常量不仅对特定类有效……这意味着使用此常量的外部类可能与包含常量的类)
- 如果您有一个定义了行为的接口,但返回值或参数值应该是特定的,那么在该接口上定义常量是完全可以接受的,以便其他实现者可以访问它们。然而,避免仅仅为了保存常量而创建接口:它可能变得和仅仅为了保存常量而创建的类一样糟糕。
回答by Marcio Aguiar
It is a BAD PRACTICEto use interfaces just to hold constants (named constant interface patternby Josh Bloch). Here's what Josh advises:
使用接口来保存常量是一种不好的做法(Josh Bloch将其命名为常量接口模式)。以下是乔希的建议:
If the constants are strongly tied to an existing class or interface, you should add them to the class or interface. For example, all of the boxed numerical primitive classes, such as Integer and Double, export MIN_VALUE and MAX_VALUE constants. If the constants are best viewed as members of an enumerated type, you should export them with an enumtype. Otherwise, you should export the constants with a noninstantiable utility class.
如果常量与现有类或接口紧密相关,则应将它们添加到类或接口中。例如,所有装箱的数字基元类,如 Integer 和 Double,都导出 MIN_VALUE 和 MAX_VALUE 常量。如果最好将常量视为枚举类型的成员,则应使用枚举类型导出它们。否则,您应该使用不可实例化的实用程序类导出常量。
Example:
例子:
// 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;
}
About the naming convention:
关于命名约定:
By convention, such fields have names consisting of capital letters, with words separated by underscores. It is critical that these fields contain either primitive values or references to immutable objects.
按照惯例,这些字段的名称由大写字母组成,单词由下划线分隔。这些字段包含原始值或对不可变对象的引用至关重要。
回答by shelfoo
In Effective Java (2nd edition), it's recommended that you use enums instead of static ints for constants.
在 Effective Java(第 2 版)中,建议您对常量使用枚举而不是静态整数。
There's a good writeup on enums in Java here: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
这里有一篇关于 Java 枚举的好文章:http: //java.sun.com/j2se/1.5.0/docs/guide/language/enums.html
Note that at the end of that article the question posed is:
请注意,在那篇文章的末尾提出的问题是:
So when should you use enums?
那么什么时候应该使用枚举呢?
With an answer of:
有一个答案:
Any time you need a fixed set of constants
任何时候您需要一组固定的常量
回答by Rob Dickerson
I agree that using an interface is not the way to go. Avoiding this pattern even has its own item (#18) in Bloch's Effective Java.
我同意使用接口不是要走的路。避免这种模式甚至在 Bloch 的Effective Java 中有自己的项目(#18)。
An argument Bloch makes against the constant interface pattern is that use of constants is an implementation detail, but implementing an interface to use them exposes that implementation detail in your exported API.
Bloch 反对常量接口模式的一个论点是常量的使用是一个实现细节,但是实现一个接口来使用它们会在导出的 API 中公开该实现细节。
The public|private static final TYPE NAME = VALUE;
pattern is a good way of declaring a constant. Personally, I think it's better to avoid making a separate class to house all of your constants, but I've never seen a reason not to do this, other than personal preference and style.
该public|private static final TYPE NAME = VALUE;
模式是声明不变的好方法。就我个人而言,我认为最好避免创建一个单独的类来容纳所有常量,但除了个人喜好和风格之外,我从未见过不这样做的理由。
If your constants can be well-modeled as an enumeration, consider the enumstructure available in 1.5 or later.
如果您的常量可以很好地建模为枚举,请考虑1.5 或更高版本中可用的枚举结构。
If you're using a version earlier than 1.5, you can still pull off typesafe enumerations by using normal Java classes. (See this sitefor more on that).
如果您使用的是 1.5 之前的版本,您仍然可以通过使用普通 Java 类来实现类型安全枚举。(有关更多信息,请参阅此站点)。