2011-05-04 84 views
0

大多数时候我在需要使用它们的相同类中定义常量。创建用于定义常量的类

但现在我必须在一个单独的类中定义所有常见的常量。我见过定义类的两个常量常量版本:

a。如果您尝试创建Consts的对象,将会导致编译时错误。

final class Consts { 
     private Consts(){} 

     public static final String TAG = "something"; 
    } 

b。如果您尝试创建Consts的对象,则会抛出运行时异常。

final class Consts { 
     public Consts(){ 
      throw new RuntimeException(); 
     } 

     public static final String TAG = "something"; 
    } 

检查这个类的机器人http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/Manifest.java 为什么他们使用了第二个版本?

我应该使用哪一个,为什么要去第二个版本?

+1

您还可以创建一个'enum'。 – romaintaz 2011-05-04 06:42:05

回答

1

从我的角度来看,没有理由使用第二种方法。这是API的误导,因为该类暴露了一个可见的构造函数,在任何情况下都会抛出异常。客户可能陷入这个陷阱。

然而,还有其他的选择,例如,你可以把Consts接口

interface Consts { 
    String TAG = "somthing" 
} 

这将允许实现该接口,从而具有“更容易”访问常量(不使用静态进口)类。另一个好处是,即使您的IDE中只有已编译的类,也可以使用查找引用。由于编译器会将常量内联到使用类中,因此很难找到对TAG的引用。如果客户端实现该接口,他们可以很容易地查找。但是,一些编码指导禁止这样做。

可能的下一个选项是枚举。 JVM将确保enum类中每个常量只有一个实例:

enum Consts { 
    TAG, OTHER, .. 
} 
3

我没有看到第二个版本的任何理由,因为第一个版本(private构造函数)完全按照您的要求进行。

另一个常见的问题是让常量持有者interface。然而,这并不是普遍认可的,并且可能导致人们接口,这通常被认为是代码味道。

+0

检查这个类的http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/Manifest.java 他们得到什么好处通过在构造函数中抛出异常。 – Vivart 2011-05-04 06:44:58

+1

由于某些原因,事情并不总是以某种方式产生,有时候这只是习惯。防止这些类的实例化非常重要,以至于任何人都无法做到他们想要的。 PS:我不喜欢界面技巧,我觉得它过度杀伤 – gd1 2011-05-04 06:49:04

+1

我不认为android的例子是一个很好的例子。构造者混淆了客户(和代码的读者)。他们应该是私人的(并且仍然可以抛出异常)。 – 2011-05-04 06:49:59

1

你可以使用两者,首先是更简单和更好,因为会导致'编译'错误,而不是运行时,即你之前发现问题。

您也可以在包中使类不是私有的(不使用public修饰符),并将其他类写入包(如果它总是写入它们),以便它们不会实例化该类。是的,Java是面向对象的,但你并不需要迂腐。 :)我从来没有见过任何人错误地实例化一类静态字段,如果他/她这样做,则不会造成任何伤害。