我见过这样的例子:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

假设我可以有一个Constants类来包装常量,并将它们声明为静态final。我几乎不知道Java,我想知道这是否是创建常量的最佳方式。


当前回答

我这样做的方法之一是通过创建一个具有常量值的“全局”类,并在需要访问常量的类中进行静态导入。

其他回答

我同意使用界面不是正确的方法。在Bloch的《Effective Java》中,避免这种模式甚至有自己的项目(#18)。

Bloch反对常量接口模式的一个论点是,常量的使用是一个实现细节,但是实现一个使用它们的接口会在导出的API中暴露该实现细节。

public|private static final TYPE NAME = VALUE;模式是一种声明常数的好方法。就我个人而言,我认为最好避免创建一个单独的类来存放所有的常量,但除了个人偏好和风格之外,我还没有看到不这样做的理由。

如果常量可以很好地建模为枚举,请考虑1.5或更高版本中可用的枚举结构。

如果您使用的是1.5以前的版本,您仍然可以通过使用普通的Java类来实现类型安全枚举。(详见这个网站)。

仅仅为了保存常量而使用接口是一种糟糕的做法(Josh Bloch将其命名为常量接口模式)。以下是乔希的建议:

如果常数与 现有的类或接口 是否应该将它们添加到类中 接口。例如,所有的 盒装的数字基元类, 如Integer和Double,导出 MIN_VALUE和MAX_VALUE常量。如果 这些常数最好看成 枚举类型的成员 应该用enum导出它们吗 类型。否则,您应该导出 带有不可实例化对象的常量 实用程序类。

例子:

// Constant utility class
package com.effectivejava.science;
public class PhysicalConstants {
    private PhysicalConstants() { }  // Prevents instantiation

    public static final double AVOGADROS_NUMBER   = 6.02214199e23;
    public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    public static final double ELECTRON_MASS      = 9.10938188e-31;
}

关于命名约定:

按照惯例,这些字段有名称 由大写字母组成的 用下划线分隔的单词。它是 重要的是,这些字段包含 要么是原始值,要么是引用 到不可变对象。

我这样做的方法之一是通过创建一个具有常量值的“全局”类,并在需要访问常量的类中进行静态导入。

这完全可以接受,甚至可能是标准。

(public/private) static final TYPE NAME = VALUE;

其中TYPE是类型,NAME是全大写的名称,空格用下划线表示,VALUE是常量值;

我强烈建议不要将常量放在它们自己的类或接口中。

附注:声明为final且为mutable的变量仍然可以更改;但是,变量永远不能指向不同的对象。

例如:

public static final Point ORIGIN = new Point(0,0);

public static void main(String[] args){

    ORIGIN.x = 3;

}

这是合法的,ORIGIN将是(3,0)点。

有一定的观点来回答这个问题。首先,java中的常量通常被声明为public、static和final。原因如下:

public, so that they are accessible from everywhere
static, so that they can be accessed without any instance. Since they are constants it
  makes little sense to duplicate them for every object.
final, since they should not be allowed to change

我永远不会为CONSTANTS访问器/对象使用接口,因为接口通常是需要实现的。这看起来是不是很有趣:

String myConstant = IMyInterface.CONSTANTX;

相反,我会在一些不同的方法中进行选择,基于一些小的权衡,所以这取决于你需要什么:

1.  Use a regular enum with a default/private constructor. Most people would define 
     constants this way, IMHO.
  - drawback: cannot effectively Javadoc each constant member
  - advantage: var members are implicitly public, static, and final
  - advantage: type-safe
  - provides "a limited constructor" in a special way that only takes args which match
     predefined 'public static final' keys, thus limiting what you can pass to the
     constructor

2.  Use a altered enum WITHOUT a constructor, having all variables defined with 
     prefixed 'public static final' .
  - looks funny just having a floating semi-colon in the code
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you still have to put explicit 'public static final' before each variable
  - drawback: not type-safe
  - no 'limited constructor'

3.  Use a Class with a private constructor:
  - advantage: you can JavaDoc each variable with an explanation
  - drawback: you have to put explicit 'public static final' before each variable
  - you have the option of having a constructor to create an instance
     of the class if you want to provide additional functions related
     to your constants 
     (or just keep the constructor private)
  - drawback: not type-safe

4. Using interface:
  - advantage: you can JavaDoc each variable with an explanation
  - advantage: var members are implicitly 'public static final'
  - you are able to define default interface methods if you want to provide additional
     functions related to your constants (only if you implement the interface)
  - drawback: not type-safe