你如何在Java中定义一类常量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/479565/
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
How do you define a class of constants in Java?
提问by Yuval Adam
Suppose you need to define a class which all it does is hold constants.
假设您需要定义一个类,它所做的只是保存常量。
public static final String SOME_CONST = "SOME_VALUE";
What is the preferred way of doing this?
这样做的首选方法是什么?
- Interface
- Abstract Class
- Final Class
- 界面
- 抽象类
- 期末班
Which one should I use and why?
我应该使用哪一种,为什么?
Clarifications to some answers:对一些答案的澄清:
Enums- I'm not going to use enums, I am not enumerating anything, just collecting some constants which are not related to each other in any way.
枚举- 我不会使用枚举,我不会枚举任何东西,只是收集一些彼此不相关的常量。
Interface- I'm not going to set any class as one that implements the interface. Just want to use the interface to call constants like so: ISomeInterface.SOME_CONST
.
接口- 我不会将任何类设置为实现接口的类。只是想使用该接口来调用常量像这样:ISomeInterface.SOME_CONST
。
采纳答案by user54579
Use a final class. for simplicity you may then use a static import to reuse your values in another class
使用 final 类。为简单起见,您可以使用静态导入在另一个类中重用您的值
public final class MyValues {
public static final String VALUE1 = "foo";
public static final String VALUE2 = "bar";
}
in another class :
在另一个班级:
import static MyValues.*
//...
if(variable.equals(VALUE1)){
//...
}
回答by Megacan
Just use final class.
只需使用 final 类。
If you want to be able to add other values use an abstract class.
如果您希望能够添加其他值,请使用抽象类。
It doesn't make much sense using an interface, an interface is supposed to specify a contract. You just want to declare some constant values.
使用接口没有多大意义,接口应该指定一个合同。您只想声明一些常量值。
回答by cletus
My preferred method is not to do that at all. The age of constants pretty much died when Java 5 introduced typesafe enums. And even before then Josh Bloch published a (slightly more wordy) version of that, which worked on Java 1.4 (and earlier).
我的首选方法是根本不这样做。当 Java 5 引入类型安全枚举时,常量的时代几乎消失了。甚至在此之前,Josh Bloch 发布了一个(稍微冗长的)版本,该版本适用于 Java 1.4(及更早版本)。
Unless you need interoperability with some legacy code there's really no reason to use named String/integer constants anymore.
除非您需要与某些遗留代码的互操作性,否则真的没有理由再使用命名字符串/整数常量。
回答by Simon Groenewolt
Or 4. Put them in the class that contains the logic that uses the constants the most
或者 4. 将它们放在包含使用常量最多的逻辑的类中
... sorry, couldn't resist ;-)
...对不起,无法抗拒;-)
回答by Jon Skeet
Your clarification states: "I'm not going to use enums, I am not enumerating anything, just collecting some constants which are not related to each other in any way."
您的澄清说明:“我不会使用枚举,我不会枚举任何东西,只是收集一些彼此不相关的常量。”
If the constants aren't related to each other at all, why do you want to collect them together? Put each constant in the class which it's most closely related to.
如果常量之间根本没有关系,为什么要将它们收集在一起?将每个常量放在与其最密切相关的类中。
回答by Sébastien RoccaSerra
As Joshua Bloch notes in Effective Java:
正如 Joshua Bloch 在 Effective Java 中所指出的:
- Interfaces should only be used to define types,
- abstract classes don't prevent instanciability (they can be subclassed, and even suggest that they are designed to be subclassed).
- 接口应该只用于定义类型,
- 抽象类不会阻止不可实例化(它们可以被子类化,甚至暗示它们被设计为子类化)。
You can use an Enum if all your constants are related (like planet names), put the constant values in classes they are related to (if you have access to them), or use a non instanciable utility class (define a private default constructor).
如果所有常量都相关(如行星名称),则可以使用 Enum,将常量值放在它们相关的类中(如果您可以访问它们),或者使用不可实例化的实用程序类(定义私有默认构造函数) .
class SomeConstants
{
// Prevents instanciation of myself and my subclasses
private SomeConstants() {}
public final static String TOTO = "toto";
public final static Integer TEN = 10;
//...
}
Then, as already stated, you can use static imports to use your constants.
然后,如前所述,您可以使用静态导入来使用您的常量。
回答by Tom Hawtin - tackline
enum
s are fine. IIRC, one item in effective Java (2nd Ed) has enum
constants enumerating standard options implementing a [Java keyword] interface
for any value.
enum
很好。IIRC,有效 Java(第 2 版)中的enum
一项具有枚举标准选项的常量,interface
用于为任何值实现 [Java 关键字] 。
My preference is to use a [Java keyword] interface
over a final class
for constants. You implicitly get the public static final
. Some people will argue that an interface
allows bad programmers to implement it, but bad programmers are going to write code that sucks no matter what you do.
我更喜欢在常量上使用 [Java 关键字] 而interface
不是 a final class
。你隐式地得到了public static final
. 有些人会争辩说,aninterface
允许糟糕的程序员实现它,但无论你做什么,糟糕的程序员都会编写糟糕的代码。
Which looks better?
哪个更好看?
public final class SomeStuff {
private SomeStuff() {
throw new Error();
}
public static final String SOME_CONST = "Some value or another, I don't know.";
}
Or:
或者:
public interface SomeStuff {
String SOME_CONST = "Some value or another, I don't know.";
}
回答by kenj0418
My suggestions (in decreasing order of preference):
我的建议(按优先顺序递减):
1) Don't do it. Create the constants in the actual class where they are most relevant. Having a 'bag of constants' class/interface isn't really following OO best practices.
1)不要这样做。在最相关的实际类中创建常量。拥有“常量包”类/接口并没有真正遵循 OO 最佳实践。
I, and everyone else, ignore #1 from time to time. If you're going to do that then:
我和其他所有人不时忽略 #1。如果你打算这样做,那么:
2) final class with private constructorThis will at least prevent anyone from abusing your 'bag of constants' by extending/implementing it to get easy access to the constants. (I know you said you wouldn't do this -- but that doesn't mean someone coming along after you won't)
2)带有私有构造函数的 final 类这至少可以防止任何人通过扩展/实现它来轻松访问常量来滥用你的“常量包”。(我知道你说过你不会这样做——但这并不意味着有人会在你不会这样做之后出现)
3) interfaceThis will work, but not my preference giving the possible abuse mention in #2.
3)界面这会起作用,但不是我的偏好,在#2中提到可能的滥用。
In general, just because these are constants doesn't mean you shouldn't still apply normal oo principles to them. If no one but one class cares about a constant - it should be private and in that class. If only tests care about a constant - it should be in a test class, not production code. If a constant is defined in multiple places (not just accidentally the same) - refactor to eliminate duplication. And so on - treat them like you would a method.
一般来说,仅仅因为这些是常量并不意味着你不应该仍然对它们应用正常的 oo 原则。如果只有一个类关心一个常量 - 它应该是私有的并且在那个类中。如果只有测试关心一个常量 - 它应该在测试类中,而不是生产代码中。如果在多个地方定义了一个常量(不仅仅是偶然相同) - 重构以消除重复。等等 - 像对待方法一样对待它们。
回答by Guizhou Feng
One of the disadvantage of private constructor is the exists of method could never be tested.
Enum by the nature concept good to apply in specific domain type, apply it to decentralized constants looks not good enough
私有构造函数的缺点之一是方法的存在永远无法被测试。
枚举本质上适用于特定领域类型的概念,将其应用于分散的常量看起来还不够好
The concept of Enum is "Enumerations are sets of closely related items".
Enum 的概念是“枚举是一组密切相关的项目”。
Extend/implement a constant interface is a bad practice, it is hard to think about requirement to extend a immutable constant instead of referring to it directly.
If apply quality tool like SonarSource, there are rules force developer to drop constant interface, this is a awkward thing as a lot of projects enjoy the constant interface and rarely to see "extend" things happen on constant interfaces
扩展/实现常量接口是一种不好的做法,很难考虑扩展不可变常量而不是直接引用它的要求。
如果应用像SonarSource这样的质量工具,有规则迫使开发者放弃固定接口,这是一件尴尬的事情,因为很多项目都喜欢固定接口,很少看到固定接口发生“扩展”的事情