在Java中如何定义一类常量?
假设您需要定义一个类,它所做的只是保存常量。
public static final String SOME_CONST = "SOME_VALUE";
这样做的首选方式是什么?
- Interface
- Abstract Class
- Final Class
我应该使用哪一个?为什么?
Clarifications to some answers:
枚举 - 我不会使用枚举,我不会枚举任何东西,只是收集一些彼此不相关的常量。
接口 - 我不会将任何类设置为实现该接口的类。 只是想使用接口来调用常量,如下所示:ISomeInterface.SOME_CONST
。
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
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
使用最终类,并定义一个私有构造函数来隐藏公共构造函数。
为了简单起见,您可以使用静态导入在另一个类的另一个类中重用您的值
:
Use a final class, and define a private constructor to hide the public one.
For simplicity you may then use a static import to reuse your values in another class
in another class :
您的澄清指出:“我不会使用枚举,我不会枚举任何内容,只是收集一些彼此不以任何方式相关的常量。”
如果这些常量彼此之间根本不相关,为什么要把它们收集在一起呢? 将每个常量放在与其最密切相关的类中。
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.
我的建议(按偏好降序排列):
1)不要这样做。 在实际类中最相关的地方创建常量。 拥有“常量包”类/接口并没有真正遵循面向对象的最佳实践。
我和其他人都会时不时地忽略#1。 如果您打算这样做,那么:
2)带有私有构造函数的最终类这至少可以防止任何人通过扩展/实现它来轻松访问常量来滥用您的“常量包” 。 (我知道你说过你不会这样做——但这并不意味着有人会在你之后不会这样做)
3)界面这会起作用,但不是我的偏好,因为可能会出现滥用情况#2 中提到。
一般来说,仅仅因为这些是常量并不意味着您不应该仍然对它们应用正常的面向对象原则。 如果只有一个类关心一个常量,那么它应该是私有的并且在该类中。 如果只有测试关心常量 - 它应该位于测试类中,而不是生产代码中。 如果在多个位置定义了一个常量(不仅仅是偶然相同) - 重构以消除重复。 等等——像对待方法一样对待它们。
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.
I, and everyone else, ignore #1 from time to time. If you're going to do that then:
2) final class with private constructor This 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)
3) interface This will work, but not my preference giving the possible abuse mention in #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.
正如 Joshua Bloch 在《Effective Java:
如果所有常量都是相关的(例如行星名称),则可以使用枚举,将常量值放入与其相关的类中(如果您有权访问它们),或者使用不可实例化的实用程序类(定义私有默认构造函数) 。
然后,如前所述,您可以使用静态导入来使用常量。
As Joshua Bloch notes in Effective Java:
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).
Then, as already stated, you can use static imports to use your constants.
我首选的方法是根本不这样做。 当 Java 5 引入类型安全枚举时,常量的时代几乎消失了。 甚至在此之前,Josh Bloch 就发布了该版本(稍微冗长一些),该版本适用于 Java 1.4(及更早版本)。
除非您需要与某些遗留代码进行互操作,否则实际上没有理由再使用命名字符串/整数常量。
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).
Unless you need interoperability with some legacy code there's really no reason to use named String/integer constants anymore.
enum
很好。 IIRC,有效的 Java(第二版)中的一项有enum
常量,枚举为任何值实现 [Java 关键字]接口
的标准选项。我的偏好是使用 [Java 关键字]
interface
而不是final class
作为常量。 您隐式地获得了public static final
。 有些人会认为接口允许糟糕的程序员实现它,但是无论你做什么,糟糕的程序员都会编写出糟糕的代码。哪个看起来更好?
或者:
enum
s are fine. IIRC, one item in effective Java (2nd Ed) hasenum
constants enumerating standard options implementing a [Java keyword]interface
for any value.My preference is to use a [Java keyword]
interface
over afinal class
for constants. You implicitly get thepublic static final
. Some people will argue that aninterface
allows bad programmers to implement it, but bad programmers are going to write code that sucks no matter what you do.Which looks better?
Or:
枚举不是这些的最佳选择吗?各种各样的东西?
Aren't enums best choice for these kinds of stuff?
对我来说最好的方法是
enum
:优点:
java:枚举类型无法实例化
The best approach for me, is
enum
:Pros:
java: enum types cannot be instantiated
只需使用最后一堂课。
如果您希望能够添加其他值,请使用抽象类。
使用接口没有多大意义,接口应该指定一个契约。 您只想声明一些常量值。
Just use final class.
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.
或者 4. 将它们放在包含使用常量最多的逻辑的类中
...抱歉,无法抗拒;-)
Or 4. Put them in the class that contains the logic that uses the constants the most
... sorry, couldn't resist ;-)
私有构造函数的缺点之一是永远无法测试方法的存在。
枚举本质上适合应用于特定领域类型,将其应用于分散常量看起来不够好
枚举
的概念是“枚举是密切相关的项的集合”。
扩展/实现常量接口是一种不好的做法,很难想象需要扩展不可变常量而不是直接引用它。
如果应用像SonarSource这样的质量工具,就会有规则迫使开发人员放弃常量接口,这是一件尴尬的事情,因为很多项目都喜欢常量接口,很少看到“扩展”事情发生在常量接口上
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".
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