2009-09-03 26 views
26

如果我想要集中声明静态常量的集合,以便它们可以在各种项目之间共享,并将它们放入类或接口(Java)中。应该将常量集合放在类或接口中吗?

在过去,我已经看到他们大多放在一个类,但我开始认为,因为类不会,也不应该实例化,也许他们会在界面更好,但接口不应该实现任何类,例如

public class ErrorCodes { 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 
} 

public interface ErrorCodes { 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 
} 

回答

27

如果他们有很强的联系,然后我把它们放在一个枚举:

public enum Error { 
    ERROR_1("-1", "foo went wrong"), 
    ERROR_2("-2", "bar went wrong"); 

    private final String id; 
    private final String message; 

    Error(String id, String message) { 
    this.id=id; 
    this.message=message; 
    } 

    public String getId() { 
    return id; 
    } 

    public String getMessage() { 
    return message; 
    } 
} 

的好处是,你可以有类型安全的代码并且您可以轻松地添加基于id的查找(通过在构造函数中构建HashMap<String,Error>或仅通过循环遍历values())。

+0

枚举实际上是一个更好的方法。我想我没有仔细阅读他的问题,以便理解他的意图。 – 2009-09-03 12:08:27

+1

我发现这是最好的解决方案,因为您可以将数字和字符串保存在一起,并从属性文件加载字符串。一切都在一个地方。 – 2009-09-03 12:10:46

+0

如果你有大量的常量,或者它在某个点之后是否会影响性能,这仍然是最好的方法吗? – Yonetmen 2018-03-08 09:30:02

4

你应该在班上做。

接口是类用户可以访问的可用方法,属性等的描述 - 通过实现接口,可以保证在接口中声明的成员对用户可用。

另一方面,类是对一个对象的描述,或者(如果你不是,那么对OO原则很难......)静态成员的占位符。我个人认为它在一些项目中非常有用,可以将一堆常量存储在Settings类中,所以我不必在整个项目中查看定义。我认为这种方法也是你追求的。

+0

在类中收集常量,并为其提供一个私有构造函数以防止它被实例化。 – 2016-07-03 13:47:25

5

使用static import应该在这里考虑(用于导入在类中定义的常量)或type-safe Enum

Interface for constants

配售常量的接口是用Java的早期流行的技术,但现在许多人认为它讨厌使用的接口,因为接口应该处理由提供的服务对象,而不是它的数据
同样,一个类使用的常量通常是一个实现细节,但将它们放在一个接口中会将它们提升到该类的公共API。

2

你应该把它们放在带有私有构造函数的类上。

public class ErrorCodes { 
    private ErrorCodes() {} // prevents instantiation 
    public static final String ERROR_1 = "-1"; 
    public static final String ERROR_2 = "-2"; 

}

或者更好的是,使用类型安全枚举。

5

这已经讨论before

为什么你不希望在一个界面中的常数的原因是,它诱使客户端类为“实行”该接口(为了访问常量无前缀他们与接口名称)。但是,您不应该 - 界面实际上不是对象的功能的接口,而是在类的外部类型中编译时的便利。

曾几何时,“恒界面”是很方便的一段时间,但它一直是“错误的”,甚至不是懒惰的借口,现在使用它,我们有import static语句。

编辑:虽然我必须同意针对您的问题中提出的场景,枚举更合适。

0

我个人认为常量应该在类中定义,原因与上面所述的相同。特别是因为一些开发人员通过在想要使用它们的类中实现接口来使用这些常量。当那个接口包含很多常量时,你不再需要查看该特定类的javadoc,因为它常常被该类的常量描述所忽略。

2

我推荐静态导入和常量接口的组合。

如果Java接口具有恒定的字段声明,请记住,这些都是隐含公共,静态和最终(见Java语言规范,Section 9.3。)因此,你总是可以省略这些修饰,只留下类型,和你的不断接口应该是这样的:

public interface Constants { 
    int AGE = 0x23; 
    String NAME = "Andrew"; 
    boolean IGNORE = true; 
} 

这应该,当然,永远如下被使用:

import static Constants.*; 

public Whatever { 
    public String method() { 
     return String.format("%s is %d%c", NAME, AGE, IGNORE ? '?' : '!'); 
    } 
} 

在我的生产代码中,我没有使用这种风格的问题,并且感觉它会导致一个非常整洁,紧凑的常量集合,并且可以处理各种类型的常量,这是枚举所不能的,并且能够被扩展如果需要,不像枚举。

另一种不是每个人都会赞同的可能性是在父接口中嵌套接口(甚至枚举类型),允许您将常量分组。这:

interface MoreConstants { 
    int MAGIC = 0xCAFEBABE; 
    interface PROPERTIES { 
     String NAME = "name"; 
    } 
    enum ERRORS { 
     ON_FIRE, ASLEEP, BROKEN, UNSURE; 
    } 
} 

和访问他们喜欢这个,假设MoreConstants的静态导入接口:

if (!PROPERTIES.NAME.equals(value)) { 
    return ERRORS.UNSURE; 
} 

当然,这些接口不应该被实现,我会考虑的做法不好。但确保这一点的唯一方法是严格的代码审查...

+0

你不会碰到的一个问题是,一些常量会在编译时被复制到生成的字节码中,而不是被引用,留给你一个ABI,你不能在不破坏东西的情况下改变它。 – 2009-09-18 18:35:52

+0

由于直接字段访问,这对于'常量类'解决方案不是问题吗? – grkvlt 2009-09-18 20:00:38

+0

是的,我认为同样的事情发生在类和接口,但我可能是错的。 +1给enum的答案 – 2009-09-19 02:47:15

相关问题