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

Yuv*_*dam 72 java class-constants

假设您需要定义一个类,它所做的就是保持常量.

public static final String SOME_CONST = "SOME_VALUE";
Run Code Online (Sandbox Code Playgroud)

这样做的首选方式是什么?

  1. 接口
  2. 抽象类
  3. 最后一堂课

我应该使用哪一个?为什么?


澄清一些答案:

枚举 - 我不会使用枚举,我不会枚举任何东西,只是收集一些与任何方式无关的常量.

接口 - 我不打算将任何类设置为实现接口的类.只想使用接口调用常量,如下所示:ISomeInterface.SOME_CONST.

use*_*579 77

使用最后一堂课.为简单起见,您可以使用静态导入在另一个类中重用您的值

public final class MyValues {
  public static final String VALUE1 = "foo";
  public static final String VALUE2 = "bar";
}
Run Code Online (Sandbox Code Playgroud)

在另一个班级:

import static MyValues.*
//...

if(variable.equals(VALUE1)){
//...
}
Run Code Online (Sandbox Code Playgroud)

  • 为了更好的可读性,我还有一个没有正文的私有默认构造函数(以及匹配的注释). (10认同)
  • 如果您需要在多个类中重用常量,那么好处是不会重复代码.我想你可以很容易地看到它的优点. (6认同)
  • 很老的答案,这个评论可能不合适,但我会使用`VALUE1.equals(variable)`,因为它避免了 NPE。 (5认同)
  • 在这里创建一个单独的类的好处在哪里?虽然我通常不把Calendar API作为设计的一个很好的例子,但就"日历类中与日历相关的常量"而言,这很好. (4认同)
  • 为什么要复制代码?只需参考其他类。我发现一个常量真正独立的情况相对罕见。 (2认同)

Jon*_*eet 37

你的澄清说明:"我不会使用枚举,我不会枚举任何东西,只是收集一些与任何方式无关的常量."

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

  • 好的.在这种情况下,只需将它们放在最接近它们所涉及的功能的类中. (10认同)
  • 乔恩 - 他们是相关的,因为他们都属于同一个功能.但是,它们并不是任何东西的枚举......它们不具有对象是"其中一种"的属性. (2认同)

ken*_*418 21

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

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

我和其他所有人不时忽略#1.如果你打算这样做那么:

2)具有私有构造函数的final类这至少可以防止任何人通过扩展/实现它来轻松访问常量来滥用你的"常量包".(我知道你说你不会这样做 - 但这并不意味着有人跟你走后不会)

3)界面这将起作用,但不是我的偏好,在#2中提到可能的滥用.

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

  • 1的问题是,有时您会在代码中注入一些对另一层类的依赖,以获取常量。 (2认同)
  • @Kodebetter 但是可以扩展/实现接口以添加更多字段。 (2认同)

Séb*_*rra 12

正如Joshua Bloch在Effective Java中所说:

  • 接口应仅用于定义类型,
  • 抽象类不会阻止不稳定性(它们可以被子类化,甚至建议它们被设计为子类).

如果所有常量都相关(如行星名称),则可以使用枚举,将常量值放在与它们相关的类中(如果您有权访问它们),或使用非实例化实用程序类(定义私有默认构造函数) .

class SomeConstants
{
    // Prevents instanciation of myself and my subclasses
    private SomeConstants() {}

    public final static String TOTO = "toto";
    public final static Integer TEN = 10;
    //...
}
Run Code Online (Sandbox Code Playgroud)

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


cle*_*tus 6

我首选的方法是根本不这样做.当Java 5引入类型安全枚举时,常量的年龄几乎消失了.甚至在此之前,Josh Bloch发布了一个(稍微冗长的罗嗦)版本,它适用于Java 1.4(及更早版本).

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

  • 好的答案,一个例子会更好。 (2认同)