接口常量的用途是什么?

我正在学习Java,并发现接口可以有公共静态和最终的字段。 到目前为止,我还没有看到这方面的例子。 这些接口常量的一些用例是什么,我可以在Java标准库中看到一些吗?

将静态成员放到一个接口(并实现这个接口)是一个不好的习惯 ,甚至有一个名字, Constant Interface Antipattern ,见Effective Java ,Item 17:

常量接口模式是接口使用不佳 。 一个类内部使用一些常量是一个实现细节。 实现一个常量接口会导致这个实现细节泄露到类的导出的API中。 对类的用户来说,类实现一个常量接口是没有意义的。 事实上,它甚至可能混淆它们。 更糟糕的是,它代表了一个承诺:如果在将来的发行版中,类被修改以便不再需要使用常量,它仍然必须实现接口以确保二进制兼容性。 如果一个非终结类实现了一个常量接口,那么它的所有子类的接口中的常量都会使其名称空间受到污染。

Java平台库中有几个常量接口,如java.io.ObjectStreamConstants 。 这些接口应该被视为exception,不应该被仿真。

为了避免常量接口的一些缺陷(因为你不能阻止人们实现它),一个适当的类与私人构造函数应该是首选(例如从维基百科借用):

 public final class Constants { private Constants() { // restrict instantiation } public static final double PI = 3.14159; public static final double PLANCK_CONSTANT = 6.62606896e-34; } 

要访问常量而不必完全限定它们(即不必使用类名称作为前缀),请使用静态导入 (自Java 5开始):

 import static Constants.PLANCK_CONSTANT; import static Constants.PI; public class Calculations { public double getReducedPlanckConstant() { return PLANCK_CONSTANT / (2 * PI); } } 

如果您在实现接口的类中使用常用的常量,那么它们很有用。

这是一个例子: http : //www.javapractices.com/topic/TopicAction.do?Id=32

但请注意,推荐的做法是在接口中使用静态导入而不是常量。 这里有一个参考: http : //www.javapractices.com/topic/TopicAction.do?Id=195

Joshua Bloch,“有效的Java – 编程语言指南”:

常量接口模式是接口使用不佳。 一个类内部使用一些常量是一个实现细节。 实现一个常量接口会导致这个实现细节泄露到类的导出的API中。 对类的用户来说,类实现一个常量接口是没有意义的。 事实上,它甚至可能混淆它们。 更糟糕的是,它代表了一个承诺:如果在将来的发行版中,类被修改以便不再需要使用常量,它仍然必须实现接口以确保二进制兼容性。 如果一个非终结类实现了一个常量接口,那么它的所有子类的接口中的常量都会使其名称空间受到污染。

我遇到了这个问题,并认为我会添加一些没有提到的东西。 总的来说,我同意帕斯卡在这里的回答。 但是,我并不认为界面上的常量是“永远”的反模式。

例如,如果你正在定义的常量是该接口的一个契约的一部分,我认为这个接口对于常量来说是个好地方。 在某些情况下,它不适合私下validation您的参数,而不会将合约暴露给您的实施的用户。 如果没有面向公众的合同,用户只能猜测你的validation与反编译和阅读你的代码。

所以,如果你实现了一个接口,并且接口有确保你的合约使用的常量(比如整数范围),那么类的用户可以通过检查接口中的常量来确保他们正在使用接口实例他们自己。 如果常量是你的实现私有的,或者你的实现是私有包或者什么的话,这将是不可能的。

javax.swing.SwingConstants接口是一个在swing类中使用静态字段的例子。 这使您可以轻松使用类似的东西

  • this.add(LINE_START, swingcomponent);
  • this.add(this.LINE_START, swingcomponent); 要么
  • this.add(SwingComponents.LINE_START, swingcomponent);

但是这个接口没有方法…

字段应该在接口中声明,以便它们更容易共享,并且可以引用而不引入额外的耦合。

来源: Java开发人员工具编码风格

处理类之间的共享常量时使用接口常量。

 public interface TestConstants { String RootLevelConstant1 = "RootLevelConstant1"; interface SubGroup1 { String SubGroupConstant1 = "SubGroup1Constant1"; String SubGroupConstant2 = "SubGroup1Constant2"; } interface SubGroup2 { String SubGroupConstant1 = "SubGroup2Constant1"; String SubGroupConstant2 = "SubGroup2Constant2"; } } 

分组是一个巨大的资产,特别是有大量的常量。

要使用,只需将它们链接在一起:

 System.out.println(TestConstants.SubGroup1.SubGroupConstant1); System.out.println(TestConstants.SubGroup2.SubGroupConstant1); System.out.println(TestConstants.RootLevelConstant1);