Java 接口常量有什么用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2659593/
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 use of interface constants?
提问by unj2
I am learning Java and just found that the Interface can have fields, which are public static and final. I haven't seen any examples of these so far. What are some of the use cases of these Interface Constants and can I see some in the Java Standard Library?
我正在学习 Java,刚刚发现接口可以具有公共静态和最终字段。到目前为止,我还没有看到任何这些例子。这些接口常量有哪些用例,我可以在 Java 标准库中看到一些吗?
采纳答案by Pascal Thivent
Putting static members into an interface (and implementing that interface) is a bad practiceand there is even a name for it, the Constant Interface Antipattern, see Effective Java, Item 17:
将静态成员放入接口(并实现该接口)是一种不好的做法,它甚至有一个名称,常量接口反模式,参见Effective Java,Item 17:
The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.
There are several constant interfaces in the java platform libraries, such as
java.io.ObjectStreamConstants
. These interfaces should be regarded as anomalies and should not be emulated.
常量接口模式是对接口的不良使用。一个类在内部使用一些常量是一个实现细节。实现一个常量接口会导致这个实现细节泄漏到类的导出 API 中。类实现常量接口对类的用户没有任何影响。事实上,它甚至可能使他们感到困惑。更糟糕的是,它代表了一种承诺:如果在将来的版本中修改了类,使其不再需要使用常量,它仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的命名空间都会被接口中的常量污染。
java平台库中有几个常量接口,例如
java.io.ObjectStreamConstants
. 这些接口应被视为异常,不应进行仿真。
To avoid some pitfalls of the constant interface (because you can't prevent people from implementing it), a proper class with a private constructor should be preferred (example borrowed from Wikipedia):
为了避免常量接口的一些陷阱(因为你不能阻止人们实现它),应该首选具有私有构造函数的适当类(从Wikipedia借用的示例):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
And to access the constants without having to fully qualify them (i.e. without having to prefix them with the class name), use a static import(since Java 5):
并且要访问常量而不必完全限定它们(即不必使用类名作为前缀),请使用静态导入(自 Java 5 起):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
回答by dcp
They are useful if you have common constants that will be used in classes that implement the interface.
如果您有将在实现接口的类中使用的公共常量,它们将非常有用。
Here's an example: http://www.javapractices.com/topic/TopicAction.do?Id=32
这是一个例子:http: //www.javapractices.com/topic/TopicAction.do?Id=32
But note that the recommended practice is to use static imports instead of constants in interfaces. Here's a reference: http://www.javapractices.com/topic/TopicAction.do?Id=195
但请注意,推荐的做法是在接口中使用静态导入而不是常量。这是一个参考:http: //www.javapractices.com/topic/TopicAction.do?Id=195
回答by Progman
The javax.swing.SwingConstants
interface is an example which got static fields which are used among the swing classes. This allows you to easily use something like
该javax.swing.SwingConstants
接口是一个示例,它获得了在 Swing 类中使用的静态字段。这使您可以轻松地使用类似
this.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
orthis.add(SwingComponents.LINE_START, swingcomponent);
this.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
或者this.add(SwingComponents.LINE_START, swingcomponent);
However this interface doesn't have methods...
但是这个接口没有方法......
回答by stacker
Joshua Bloch, "Effective Java - Programming Language Guide":
Joshua Bloch,“有效的 Java - 编程语言指南”:
The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.
常量接口模式是接口使用不当。一个类在内部使用一些常量是一个实现细节。实现一个常量接口会导致这个实现细节泄漏到类的导出 API 中。类实现常量接口对类的用户没有任何影响。事实上,它甚至可能使他们感到困惑。更糟糕的是,它代表了一种承诺:如果在将来的版本中修改了类,使其不再需要使用常量,它仍然必须实现接口以确保二进制兼容性。如果一个非final类实现了一个常量接口,那么它的所有子类的命名空间都会被接口中的常量污染。
回答by jared
I use interface constants when dealing with shared constants between classes.
我在处理类之间的共享常量时使用接口常量。
public interface TestConstants
{
String RootLevelConstant1 = "RootLevelConstant1";
interface SubGroup1
{
String SubGroupConstant1 = "SubGroup1Constant1";
String SubGroupConstant2 = "SubGroup1Constant2";
}
interface SubGroup2
{
String SubGroupConstant1 = "SubGroup2Constant1";
String SubGroupConstant2 = "SubGroup2Constant2";
}
}
The grouping is a huge asset, especially with a large set of constants.
分组是一项巨大的资产,尤其是对于大量常量。
To use, you simply chain them together:
要使用,您只需将它们链接在一起:
System.out.println(TestConstants.SubGroup1.SubGroupConstant1);
System.out.println(TestConstants.SubGroup2.SubGroupConstant1);
System.out.println(TestConstants.RootLevelConstant1);
回答by Master Mind
fields should be declared in an interface so that they are easier to share and can be referenced without introducing extra coupling.
字段应该在接口中声明,以便它们更容易共享并且可以在不引入额外耦合的情况下被引用。
回答by akagixxer
I came across this question and thought I'd add something that was not mentioned. In general, I agree with Pascal's answer here. However, I don't think constants on an interface are "always" an antipattern.
我遇到了这个问题,并认为我会添加一些未提及的内容。在一般情况下,我同意帕斯卡尔的答案在这里。但是,我不认为接口上的常量“始终”是反模式。
For example, if the constants that you are defining are part of a contract for that interface, I think the interface is a great place for the constants. In some cases, its just not appropriate to privately validate your parameters without exposing the contract to the users of your implementation. Without a public facing contract, users can only guess what your validating with, short of decompiling the class and reading your code.
例如,如果您定义的常量是该接口合同的一部分,我认为该接口是常量的好地方。在某些情况下,在不向实现的用户公开合同的情况下私下验证参数是不合适的。如果没有面向公众的合同,用户只能猜测您的验证内容,而无需反编译类和阅读您的代码。
So if you implement an interface and the interface has the constants you use in ensuring your contracts (like integer ranges for example), then a user of your class can be sure they are using the interface instance correctly by checking against the constants in the interface themselves. This would be impossible if the constants were private to your implementation or your implementation was package private or something.
因此,如果您实现了一个接口并且该接口具有您用于确保合同的常量(例如整数范围),那么您的类的用户可以通过检查接口中的常量来确保他们正确使用了接口实例他们自己。如果常量对于您的实现是私有的,或者您的实现是包私有的或其他什么,这将是不可能的。
回答by Blessed Geek
"The constant interface pattern is a poor use of interfaces"
“常量接口模式是接口使用不当”
Whoever concocted this hypothesis, however a guru he/she may be, concocted it on the basis of the need to continue implementing bad habits and practices efficiently. The hypothesis is based on the promotion of the validity of bad software design habits.
无论是谁编造了这个假设,无论他/她是什么大师,都是基于继续有效地实施不良习惯和做法的需要而编造的。该假设基于促进不良软件设计习惯的有效性。
I wrote a response rebuttal against that hypothesis here: What is the best way to implement constants in Java?explaining the baseless-ness of this hypothesis.
我在这里写了一个反驳这个假设的回应:在 Java 中实现常量的最佳方法是什么?解释这个假设的毫无根据。
For 10 years that question had stayed open, until it was closed within 2 hours after I posted my reasons dejustifying this hypothesis, thus exposing UNWILLINGness for debate by those who hold on to this misguided hypothesis dearly.
10 年来,这个问题一直悬而未决,直到在我发布了我的理由来否定这个假设后的 2 小时内它被关闭,从而暴露了那些坚持这一错误假设的人不愿意进行辩论。
These are the points I expressed against the hypothesis
这些是我针对假设表达的观点
The basis for holding this hypothesis is the need for methods and RESTRICTIVE rules to cope with the effects of bad software habits and methodologies.
The proponents of the sentiment "The constant interface pattern is a poor use of interfaces"are unable to provide any reasons other than those caused by the need to cope with the effects of those bad habits and practices.
Solve the fundamental issue.
And then why not make full use and exploit every language feature of the Java language structure to your own convenience. No Hymanets Required. Why invent rules to barricade your ineffective lifestyle to discriminate and incriminate more effective lifestyles?
支持这一假设的基础是需要方法和限制性规则来应对不良软件习惯和方法的影响。
“不变的接口模式是接口的不良使用”这种观点的支持者除了需要应对那些不良习惯和做法的影响之外,无法提供任何其他原因。
解决根本问题。
那么为什么不充分利用和利用 Java 语言结构的每个语言特性来方便您呢?不需要夹克。为什么要发明规则来限制您无效的生活方式以歧视和定罪更有效的生活方式?
The fundamental issue
根本问题
is information organisation. Information mediating the process, nd the behaviour of that information should first be understood, along with the so-called business rules - before engineering or supplementing solutions to the process. Such method of information organization was called data normalization a few decades ago.
是信息组织。在对流程进行设计或补充解决方案之前,应首先了解作为流程中介的信息和该信息的行为,以及所谓的业务规则。这种信息组织方式在几十年前被称为数据规范化。
Then only the engineering of a solution be possible because aligning the granularity and modularity of the components of a solution with the granularity and modularity of the components of the information is the optimal strategy.
那么只有解决方案的工程化才是可能的,因为将解决方案组件的粒度和模块化与信息组件的粒度和模块化对齐是最佳策略。
There are two or three significant obstacles toward organizing information.
组织信息有两到三个重大障碍。
The lack of perception for the need of data-model "normalization".
EF Codd's statements on data normalization are flawed, defective and ambiguous.
The latest fad masquerading as agile engineering is the misguided notion that one should not plan and condition the organization of modules ahead because you can refactor as you go. Refactoring and continuous change without being impeded by future discoveries is used as the excuse. Essential discoveries of behaviour of process information is then, by using accounting tricks to delay profits and assetization, wherefore essential knowledge and their treatment is deemed not needed now.
缺乏对数据模型“规范化”需求的认识。
EF Codd 关于数据规范化的陈述是有缺陷的、有缺陷的和模棱两可的。
伪装成敏捷工程的最新时尚是一种被误导的观念,即不应预先计划和调节模块的组织,因为您可以随时进行重构。以不受未来发现阻碍的重构和持续更改为借口。然后,通过使用会计技巧来延迟利润和资产化,过程信息行为的基本发现,因此现在认为不需要基本知识及其处理。
Using Interface Constants is Good Practice.
使用接口常量是很好的做法。
Don't make up rules or issue any fatwa against it just because you love your ad-hoc hit-and-run programming habits.
不要仅仅因为你喜欢你的即兴即跑编程习惯就制定规则或发布任何针对它的教令。
Do not ban gun ownership with the reason that there are people who either do not know how to handle guns or are prone to abuse guns.
不要因为有些人不知道如何使用枪支或容易滥用枪支而禁止拥有枪支。
If the rules you concoct are meant for programming novices unable to code professionally and that you count yourself amongst them then say so - do not declare your fatwa as applicable to properly normalized data-models.
如果你编造的规则是为无法专业编码的编程新手而设计的,并且你把自己算在他们之中,那么就这么说 - 不要声明你的教令适用于正确规范化的数据模型。
A silly reasoning - Interfaces were not intended by the flounders of the Java language to be used that way?
一个愚蠢的推理 - Java 语言的比目鱼不打算以这种方式使用接口?
I don't care what the original intentions of the founding fathers had for the US Constitution. I don't care about the unwritten uncodified intentions. I only care about what is literarily codified in the written Constitution and how I can exploit them for the effective functioning of society.
我不在乎开国元勋对美国宪法的初衷是什么。我不在乎不成文的未编纂意图。我只关心成文宪法中字面上编纂的内容以及我如何利用它们来有效地发挥社会作用。
I only care about what the Java language/platform specs allow me and I intend to exploit them to the full to afford me a medium to express my software solutions efficiently and effectively. No Hymanets required.
我只关心 Java 语言/平台规范允许我做什么,我打算充分利用它们,为我提供一种有效和有效地表达我的软件解决方案的媒介。不需要夹克。
Use of Enum Constants is actually Horrible Practice.
使用枚举常量实际上是一种可怕的做法。
It requires writing extra code to map parameter to value. The fact that the founders of Java did not provide for parameter-value mapping without your writing that mapping code demonstrates Enum Constants are just as unintended use of Java language.
它需要编写额外的代码来将参数映射到值。Java 的创始人在没有您编写映射代码演示 Enum Constants 的情况下没有提供参数值映射这一事实与 Java 语言的意外使用一样。
Especially since you are not encouraged to normalize and componentize your parameters, there would be a false impression that parameters mixed into an Enum bag belong to the same dimension.
特别是因为不鼓励您对参数进行规范化和组件化,所以会产生一种错误的印象,即混合到 Enum 包中的参数属于同一维度。
Constants are API Contract
常量是 API 契约
Don't forget that. If you designed and normalized your data-model, and they include constants,then those constants are contracts. If you did not normalize your data-model, then you should conform to fatwas given on how to practice restrictive coding to cope with that bad habit.
不要忘记那个。如果您设计并规范了您的数据模型,并且它们包含常量,那么这些常量就是契约。如果您没有规范化您的数据模型,那么您应该遵守关于如何练习限制性编码以应对这种坏习惯的教令。
Therefore, Interfaces are a perfect way of implementing Constants' contract.
因此,接口是实现常量契约的完美方式。
A strange presumption - What if the interface inadvertently gets implemented.
一个奇怪的假设 - 如果接口无意中实现了怎么办。
Yup. Anyone could inadvertently implement any interface inadvertently. Nothing will stand in the way of such inadvertent programmers.
是的。任何人都可能不经意地实现任何接口。没有什么能阻挡这种不经意的程序员。
Design and normalize your data-model against leakage
设计和规范您的数据模型以防止泄漏
Do not place restrictive decrees to protect presumed bad practices that cause leaking of uncontracted/stray parameters into API. Solve the fundamental issue, rather than place the blame on Interface Constants.
不要制定限制性法令来保护可能导致未签约/杂散参数泄漏到 API 中的假定不良做法。解决根本问题,而不是将责任归咎于接口常量。
Not using an IDE is bad practice
不使用 IDE 是不好的做法
A normal functioning and EFFECTIVE programmer is not there to prove how long she can stay underwater, how far she could walk in blistering heat or wet thunderstorms. She is to use an efficient tool like a car or bus or at least a bike to take her 10 miles to work everyday.
一个正常运作和有效的程序员不会在那里证明她可以在水下呆多久,她可以在酷热或潮湿的雷暴中行走多远。她将使用一种高效的工具,例如汽车、公共汽车或至少一辆自行车,每天上班 10 英里。
Do not place restrictions on fellow programmers just because you have an esoteric asceticism obsession with IDE-less programming.
不要仅仅因为您对无 IDE 编程有一种深奥的禁欲主义痴迷而对其他程序员施加限制。
A couple frameworks are designed to help programmers continue practicing bad habits efficiently.
一些框架旨在帮助程序员继续有效地练习坏习惯。
OSGI is such a framework. And so is the decree against Interface Constants too.
OSGI 就是这样一个框架。针对接口常量的法令也是如此。
Therefore the conclusive answer ...
因此,结论性的答案......
Interface constants are an effective and efficient way to place into Contract well-designed and normalized components of a data-model.
接口常量是一种有效且高效的方式,可以将数据模型的精心设计和规范化的组件放入合同中。
Interface constants in an appropriately named private interface nested in a class file are also good practice to group all your private constants rather than scatter them all over the file.
嵌套在类文件中的适当命名的私有接口中的接口常量也是将所有私有常量分组而不是将它们分散在整个文件中的好习惯。
回答by Zhili
There are answers that are very resonable.
有一些非常合理的答案。
But I have some thoughts about this question. (may be wrong)
但我对这个问题有一些想法。(可能有误)
In my opinion, the fields in a interface, should not be constants to the whole project, they are only means for the interface and the interfaces extend it and the classes which are implement these interfaces or have a close relation with them. They should be used within a certain range not global.
在我看来,接口中的字段不应该是整个项目的常量,它们只是接口的手段,接口扩展了它以及实现这些接口或与它们有密切关系的类。它们应该在一定范围内使用,而不是全局使用。
回答by Nakamura
I came across this old question several times now and the accepted answer still confuse me. After a lot of thinking, I think this question can be further clarified.
我现在多次遇到这个老问题,接受的答案仍然让我感到困惑。想了很久,觉得这个问题可以进一步澄清。
Why use Interface Constant?
为什么要使用接口常量?
Just compare them:
只需比较它们:
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
vs
对比
public interface Constants {
public double PI = 3.14159;
public double PLANCK_CONSTANT = 6.62606896e-34;
}
Same usage. Much less code.
用法一样。少了很多代码。
Bad practice?
不好的做法?
I think @Pascal Thivent 's answer has the wrong emphasis, here is my version of it:
我认为@Pascal Thivent 的回答有错误的强调,这是我的版本:
Putting static members into an interface (and implementing that interface) is a bad practice.
将静态成员放入接口(并实现该接口)是一种不好的做法。
The quote from Effective Java has the assumption of the constant interface being implemented by others, which I think should not (and will not) happen.
Effective Java 中的引用假设了其他人正在实现的常量接口,我认为这不应该(也不会)发生。
When you create an constant interface named something like Constants
, it should not be implemented by anyone. (though technically possible, which is the only issue here)
当你创建一个名为 的常量接口时Constants
,它不应该被任何人实现。(虽然技术上可行,这是这里唯一的问题)
It won't happen in the standard library
它不会发生在标准库中
The standard library cannot afford any possible misuse of the design, so you just won't see any there.
标准库无法承受任何可能的设计误用,因此您在那里看不到任何东西。
However, for daily projects of normal developers, using constants interface is a lot easier because you do not need to worry about static
, final
, empty constructor
, etc, and it will NOT cause any bad design issue. The only downside I can think of is that it still has the name of "interface", but nothing more than that.
然而,对于普通开发人员的日常项目,使用常量接口是一个容易得多,因为你不必操心static
,final
,empty constructor
等,并不会造成任何不良的设计问题。我能想到的唯一缺点是它仍然有“接口”的名字,但仅此而已。
Never-ending debate
无休止的辩论
At the end, I think everyone is just quoting from books, and giving opinions and justifications to their stands. No exception for me. Maybe the decision is still up to the developers of each project. Just go ahead to use it if you feel comfortable. The best we can do is to make it consistent throughout the project.
归根结底,我认为每个人都只是引用书本,并为自己的立场提出意见和理由。我也不例外。也许决定仍然取决于每个项目的开发人员。如果您觉得舒服,请继续使用它。我们能做的最好的事情就是让它在整个项目中保持一致。