论坛首页 Java企业应用论坛

如何声明与组织常量

浏览 2698 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-04-29  
最近涉及了两个项目,两者对声明常量的方式都不尽相同,一个用接口进行封装,另一个用类进行封装。

首先,我们来看看前者的做法:

public interface IConstants {
		
	public static String CONSTANT_STRING = "iconstant_string";

}


注意在引用该常量前,必须先实现IConstants接口,然后直接引用即可:

public class Main implements IConstants {

	public static void main(String[] args) {
		// Access constants in interface
		System.out.println(CONSTANT_STRING);		
	}

}


接着,我们再来看看后者的做法:

public class Constants {
	
	/**
	 * A private constructor to suppress the default constructor.
	 */
	private Constants() {
	}
	
	public final static String CONSTANT_STRING = "constant_string";

}


在需要使用常量的地方引用即可:

	// Access constants in class
	System.out.println(Constants.CONSTANT_STRING);


简单地比较两者,我们很容易看出:
1、前者直接引用常量,显得非常简洁。但一旦实现了IConstants接口,便间接包含了其声明的所有常量,略显冗余。
2、虽然后者的引用方式相对有点复杂(其实也不会 ),但有效避免了冗余。

我个人倾向于后者的做法,因为我觉得声明与组织常量可以遵循以下几个原则:
1、常量只对有需要的客户(类或接口)可见。
2、常量对客户而言应该是“只读”。
3、常量的声明和组织容易阅读。

其中最重要的应该是可见性的问题。前者(使用接口封装常量)确实可以更好地控制可见性,因为接口声明的常量只对实现了该接口的类可见,而后者(使用类封装常量)默认是全局可见。诚如Josh Bloch在《Effective Java》中论述过,假设一个类实现了IConstants接口,当然,它可以轻松获得常量。但是,这样一来,该类的所有子类也默认继承了IConstants的所有常量,也许这并不是我们想要的。

最后我引用Josh Bloch的一段话作为结束吧,呵呵,希望大家能分享一下自己的经验
引用

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class's exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface








   发表时间:2008-04-29  
前者为什么不能像后者那样import IConstants使用?还写这么长的文章分析,服了...
0 请登录后投票
   发表时间:2008-04-29  
Readonly 写道
前者为什么不能像后者那样import IConstants使用?还写这么长的文章分析,服了...


Of course you can

但我觉得前者的做法(implements IConstants)有两个优点:
1、更加有效地控制常量的访问——常量只对实现该接口的类可见。
2、引用常量更加简洁。

而import的做法无法发挥这两个优点。
0 请登录后投票
   发表时间:2008-04-29  
Java 1.5已经有enum了。。。
0 请登录后投票
   发表时间:2008-04-29  
1.5还有static import
8 请登录后投票
   发表时间:2008-04-29  
static import用的多
0 请登录后投票
   发表时间:2008-04-29  
Eastsun 写道
Java 1.5已经有enum了。。。


嗯,enum是声明常量的一个不错的选择。但是,对于更有效地组织常量方面,相对于类或接口来说,还是略显逊色。
0 请登录后投票
   发表时间:2008-04-29  
Readonly 写道
1.5还有static import

andy.wang 写道
static import用的多


static import主要有两个优点:
1、简洁的引用,类似于用接口封装的方式。
2、对常量可见性的有效控制,常量只对static import的类可见。

所以,我觉得Tiger推出static import的本意应该是想给“Constant Interface Antipattern”(也就是上面所说的“用接口封装常量”)提供一个解决方案。但SUN自己也承认,static import应该只在“需要对一或两个类的静态变量频繁访问的时候才用”(use it when you require frequent access to static members from one or two classes),滥用有话会严重损害程序的可阅读性和可维护性。

请参考:http://java.sun.com/j2se/1.5.0/docs/guide/language/static-import.html

Anyway,我之所以再次提出“用接口封装常量”来讨论,因为它在组织常量与控制常量的可见性方面,还是非常值得借鉴的。

谢谢大家的讨论,希望有更多人分享自己的经验:)
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics