在Java中定义几个不相关类中使用的常量的位置

时间:2016-01-07 11:53:46

标签: java enums constants

在Java中定义常量的位置问题在论坛中出现过很多次,但我很难找到一个我觉得舒服的解决方案。

为简单起见,假设我有两个类:WriteMyDataReadMyData。 None是另一个的子类。这两个类共享两个对其操作至关重要的常量:String DELIMITERint LENGTH。将来我可能想要更改这些常量的值,以便在适当的地方定义它们。

共识似乎常常偏向enum类型。但是,在我的情况下,枚举没有任何内容,因此我的enum中只有一个项目,我称之为DEFAULT

public enum DataSettings {
    DEFAULT(",", 32);

    private final String delimiter;
    private final int length;

    DataSettings(String delmiter, int length) {
        this.delimiter = delimiter;
        this.length = length;
    }

    public String getDelimiter() { return delimiter; }
    public int getLength() { return length; }
}

因此,在我的两个类中,我通过DataSettings.DEFAULT.getDelimiter()DataSettings.DEFAULT.getLength()访问常量。

这是非常好的OO风格吗? enum的使用是否过度杀伤?如果我不使用enum,我该怎么做呢?为常量创建一个接口似乎不受欢迎,而且我的类似乎没有自然的超类来源。在enum中只有一个默认项是初学者错误吗?

8 个答案:

答案 0 :(得分:3)

只需创建类似was_gifted()类的内容,您将放置所有常量。

例如:

Constants.java

并按照您的意愿使用它们:

public class Constants {
    public static final String DELIMITER = "-";
    public static final int LENGTH = 1;
}

答案 1 :(得分:2)

如果只有那两个constans并且不会有更多,你可以有一个像

这样的界面
interface DataSetting
{
   String DELIMITER = ",";
   int LENGTH = 32;
}

如果你需要通过属性启动

public class DataSetting {

   public static String DELIMITER = ",";
   public static int LENGTH = 32;

  static {
    DELIMITER = System.getProperty("delimiter");
    LENGTH = Integer.parseInt(System.getProperty("length"));
     // or from config 
  }
}

答案 2 :(得分:1)

当没有任何可以枚举的内容时使用enum确实是不好的做法。

另一个提到的替代方案,使用interface也是一个糟糕的选择。有效的Java,第19项最好地描述了它:

  

第19项:仅使用界面来定义类型

     

当类实现接口时,接口用作类型,可用于引用类的实例。因此,类实现接口应该说明客户端可以对类的实例做什么。为任何其他目的定义接口是不合适的。

     

一种未通过此测试的接口是所谓的常量接口。这样的接口不包含任何方法;它仅由静态最终字段组成,每个字段都输出一个常量。使用这些常量的类实现接口,以避免使用类名限定常量名称。

正确的实现是定义一个不可实例化的实用程序类:

public class Constants {
    private Constants(){} // Private constructor prevents instantiation AND subclassing

    public static final String DELIMITER = "-";
    public static final int LENGTH = 1;
}

为方便起见,您可以静态导入代码中的常量:

import static com.example.Constants.*;

public class Test {
    public static void main(String[] args){
        System.out.println(DELIMITER); // prints "-"
    }
}

答案 3 :(得分:0)

只有1值的枚举可能没有多大意义,尽管如果计划扩展它可能包含的任何值,它可能会有用。

您所说的替代方法如下:

  1. 有一个暴露项目范围常量的公共类。当您的应用程序启动时,您可以使此类从某个配置文件中加载它的值,以便您可以控制这些常量的值。

  2. 为您的阅读和写作方法设置一组单独的方法,后缀为WithDefaultValues。反过来,这些方法将调用您的其他方法并传入默认参数。

  3. 作为旁注,简单地重载您已经拥有的方法可能是有意义的,因此您有一个默认为这些常量的实现。如果是这种情况,请务必在方法签名中记录。

答案 4 :(得分:0)

IMO,Enum在这种情况下是矫枉过正的。 Enums用于枚举。

对于全局常量,您可以在java类或java接口中创建公共静态final类属性,尽管最新的不是常用方法(请参阅Interfaces with static fields in java for sharing 'constants'

答案 5 :(得分:0)

我建议另一个不使用WriteMyDataReadMyData中任何常量的解决方案。

将分隔符和长度作为构造函数参数传递。这样,您就可以使用可能使测试更容易的参数对这些类进行单元测试。

当每个实例对分隔符和长度使用相同的值很重要时,两者都应在同一位置实例化并供客户端使用。创建实例的位置是使分隔符和长度值具有常量的适当位置。

答案 6 :(得分:0)

您可以创建一个界面 默认情况下,界面中的常量是静态的和最终的 您可以通过引用接口来使用这些变量。

public interface AnyNameInterface {
   String AnyVar ="DEMO";
   Double AnyVar_2 = 123.00;
}

用作:

AnyNameInterface.AnyVar
AnyNameInterface.AnyVar_2

答案 7 :(得分:0)

我想补充一点,即使有枚举的东西,枚举也不能总是被用作常量的容器,即使它们很好。

例如, javax.ws.rs.Path 定义String类型的单个注释类型元素。但是,这不会编译:

@Path(MyEnum.BASE_PATH) 也不会 @Path(MyEnum.BASE_PATH.name())

此外,在 可能无法定义类本身或某些常见超类的常量的情况下,讨论通常似乎是在定义类中的常量与一个界面。第三种选择可以是在注释中定义它们。

public @interface MyAnnotation {
  String QUESTIONS = "/questions";
  String ANSWERS = "/answers"; }

注释方法避开"常量界面"陷阱。在我的理解中,这个缺陷并不是说接口作为一个常量容器本身就是一个坏主意,问题是当调用者决定实现接口时,而不是通过例如访问常量。静态导入。