如何在Java中定义一类常量?

如何在Java中定义一类常量?,java,class-constants,Java,Class Constants,假设您需要定义一个类,它所做的只是保存常量 public static final String SOME_CONST = "SOME_VALUE"; 这样做的首选方式是什么 接口 抽象类 期末班 我应该使用哪一个?为什么 对一些答案的澄清: 枚举-我不会使用枚举,我不会枚举任何东西,只是收集一些彼此之间没有任何关联的常量 接口-我不会将任何类设置为实现接口的类。只想使用接口调用常量,如:isomointerface。一些常量只使用final类 如果希望能够添加其他值,请使用抽象类 使用接口

假设您需要定义一个类,它所做的只是保存常量

public static final String SOME_CONST = "SOME_VALUE";
这样做的首选方式是什么

  • 接口
  • 抽象类
  • 期末班
  • 我应该使用哪一个?为什么


    对一些答案的澄清:

    枚举-我不会使用枚举,我不会枚举任何东西,只是收集一些彼此之间没有任何关联的常量

    接口-我不会将任何类设置为实现接口的类。只想使用接口调用常量,如:
    isomointerface。一些常量只使用final类

    如果希望能够添加其他值,请使用抽象类

    使用接口没有多大意义,接口应该指定一个契约。您只需要声明一些常量值。

    不是这些类型的最佳选择吗?

    使用final类。 为了简单起见,您可以使用静态导入在另一个类中重用您的值

    public final class MyValues {
      public static final String VALUE1 = "foo";
      public static final String VALUE2 = "bar";
    }
    
    在另一类中:

    import static MyValues.*
    //...
    
    if(variable.equals(VALUE1)){
    //...
    }
    

    我的首选方法是根本不这样做。当Java5引入类型安全枚举时,常量的时代几乎消失了。甚至在那之前,Josh Bloch发布了一个(稍微罗嗦一点的)版本,它适用于Java1.4(以及更早的版本)


    除非您需要与某些遗留代码的互操作性,否则实在没有理由再使用命名字符串/整数常量。

    或4。将它们放入包含使用常量最多的逻辑的类中


    。。。对不起,无法抗拒;-)

    你的解释是:“我不会使用枚举,我不会枚举任何东西,只是收集一些彼此之间没有任何关联的常量。”


    如果常数之间根本不相关,为什么要将它们收集在一起?将每个常量放在它最密切相关的类中。

    正如Joshua Bloch在《有效Java》中所指出的:

    • 接口只能用于定义类型
    • 抽象类不阻止实例化(它们可以被子类化,甚至暗示它们被设计成子类)
    如果所有常量都相关(如行星名称),则可以使用枚举,将常量值放入与其相关的类中(如果您有权访问它们),或者使用不可实例化的实用程序类(定义专用默认构造函数)


    然后,如前所述,您可以使用静态导入来使用常量。

    enum
    s就可以了。IIRC,有效Java(第二版)中的一项具有
    枚举
    常量,枚举实现[Java关键字]
    接口
    的任何值的标准选项

    public static final String SOME_CONST = "SOME_VALUE";
    
    我更喜欢使用[Java关键字]
    接口,而不是
    最终类
    作为常量。您隐式地获得了
    公共静态final
    。有些人会争辩说,
    接口
    允许差劲的程序员实现它,但差劲的程序员无论做什么都会写出糟糕的代码

    哪个看起来更好

    public final class SomeStuff {
         private SomeStuff() {
             throw new Error();
         }
         public static final String SOME_CONST = "Some value or another, I don't know.";
    }
    
    或:

    我的建议(按优先顺序递减):

    1) 不要这样做。在实际类中创建最相关的常量。拥有一个“常量包”类/接口并不是真正遵循OO最佳实践

    一、 而其他人,时不时地忽略#1。如果你打算这样做,那么:

    2) 带有私有构造函数的最终类这将至少防止任何人滥用您的“常量包”,方法是扩展/实现它以方便访问常量。(我知道你说过你不会这样做,但这并不意味着有人会在你之后不这样做)

    3) 接口这会起作用,但我不喜欢在第2章中提到可能的滥用

    一般来说,仅仅因为这些是常量并不意味着您不应该仍然对它们应用正常的oo原则。如果只有一个类关心常量,那么它应该是私有的,并且在该类中。如果只有测试关心常量,那么它应该在测试类中,而不是在生产代码中。如果在多个位置定义了常数(不仅仅是意外地定义了同一个),则重构以消除重复。以此类推——像对待方法一样对待他们


  • 私有构造函数的缺点之一是方法的存在永远无法测试

  • 枚举的本质概念很好地应用于特定的域类型,将其应用于分散的常量看起来还不够好

  • 枚举的概念是“枚举是一组密切相关的项”

  • 扩展/实现一个常量接口是一种糟糕的做法,很难考虑扩展一个不变常量而不是直接引用它的需求

  • 如果应用SonarSource这样的质量工具,有规则迫使开发人员放弃常量接口,这是一件很尴尬的事情,因为很多项目都喜欢常量接口,很少看到在常量接口上发生“扩展”的事情


  • 这里有一些类似的讨论:。我会使用带有私有构造函数的最后一个类,这样它就不能被实例化。抱歉,但是“我不打算使用枚举”将这个问题变成了“做蠢事的最佳方式是什么?”我并不是说你要实现接口。但使用接口来实现这一点毫无意义。最后一个类:)Enum有什么问题?您可以一直使用它来收集“一些彼此不相关的常数”。嗯?从概念上讲,如果常量不相关,枚举是一个错误的选择。枚举表示相同类型的可选值。这些常量不是可选的,它们甚至可能不是相同的类型(有些可能是字符串,有些是整数等)。这不是一个好主意。这会在类之间创建依赖关系
    public interface SomeStuff {
         String SOME_CONST = "Some value or another, I don't know.";
    }