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

时间:2009-01-26 12:00:10

标签: java class-constants

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

public static final String SOME_CONST = "SOME_VALUE";

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

  1. 接口
  2. 抽象类
  3. 最终班级
  4. 我应该使用哪一个?为什么?

    <小时/> 澄清一些答案:

    枚举 - 我不打算使用枚举,我不会枚举任何内容,只是收集一些彼此无关的常量。

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

10 个答案:

答案 0 :(得分:71)

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

public final class MyValues {
  public static final String VALUE1 = "foo";
  public static final String VALUE2 = "bar";
}

在另一个班级:

import static MyValues.*
//...

if(variable.equals(VALUE1)){
//...
}

答案 1 :(得分:36)

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

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

答案 2 :(得分:19)

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

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

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

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

3)界面这样可行,但不是我的偏好,可能会在#2中提及可能的滥用行为。

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

答案 3 :(得分: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;
    //...
}

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

答案 4 :(得分:6)

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

除非您需要与某些遗留代码进行互操作,否则我们就没有理由再使用命名字符串/整数常量了。

答案 5 :(得分:3)

只需使用最终课程。

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

使用接口没有多大意义,接口应该指定合同。您只想声明一些常量值。

答案 6 :(得分:3)

这些东西不是enums最佳选择吗?

答案 7 :(得分:3)

enum很好。 IIRC,有效Java(第二版)中的一个项目有enum个常量,用于枚举为任何值实现[Java关键字] interface的标准选项。

我的偏好是对interface使用[Java关键字] final class作为常量。你暗中得到了public static final。有些人会争辩说interface允许糟糕的程序员实现它,但是不管你做什么,糟糕的程序员都会编写糟透的代码。

哪个看起来更好?

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

或者:

public interface SomeStuff {
     String SOME_CONST = "Some value or another, I don't know.";
}

答案 8 :(得分:1)

或4.将它们放在包含使用最常量

的逻辑的类中

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

答案 9 :(得分:0)

对我来说最好的方法是enum

public enum SomeApiConstants {;

    public static final String SOME_CONST = "SOME_VALUE";

    //may be in hierarchy
    public enum ApiMapping {;
        public static final String VERSION = "/version";
        public static final String VERSION_LIST = "/list/{type}";
    }
}

优点:

  • 干净的代码
  • 不需要定义私有构造函数
  • 尝试实例化在编译时被验证为 java: enum types may not be instantiated
  • 防止克隆和反序列化