Static Import 和 Constant Interface Antipattern
某日,一同事向我询问 Java 5 中为何要引入 Static Import,一时答不上来,自责平日里“学而不思”,Java 5 的发布已经是六年前(2004年9月30日)的事情了,到现在也只是“知其然”,而不“知其所以然”,之后遂决定对这一问题做一番探究。
此番探究从 SUN 的官方解释入手,从 Static Import 一文中,可以明白引入的目的在于解决 Constant Interface Antipattern。那么什么是 Constant Interface Antiparttern ? 这要从访问 static member 开始说起,如下面代码所示,在 member 之前需要有其对应的类名。
double r = Math.cos(Math.PI * theta); |
这样的用法本是合情合理,但是“懒惰”的程序员抱怨其太繁琐了:我要直接访问常量,无需加以类名!于是就生出一个法子:把 static member 放到 interface 里,然后 inherit 这个 interface。–这种做法就是 Constant Interface Antiparttern,这一术语可以追溯到 Joshua Bloch 所著的《Effictive Java》,关于这一问题的详细描述,可以参考原作(P98, Item 19: Use interface only to define types),当然,也可以从 Google books 里找到,请看这里。
在原作当中,Joshua Bloch 是这样描述 constant interface:
Such an interface contains no methods; it consists solely of static final fields, each exporting a constant. Classes using these constants implement the interface to avoid the need to qualify constant names with a class name.
尽管这种做法时常出现,甚至在 Java SE API 当中也能找到,例如 java.io.ObjectStreamConstants,但是这种做法却是不值得提倡的,Joshua Bloch 归纳了三点原因:
That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail leak into the class’s exported API.
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 namespace polluted by the constants in the interface
与此类似,从 Wikipedia 上查看 Constant Interface 的词条,可以看到相差无几的解释,也可以看到详细的代码示例,也就省去在这里展示代码的必要了。
可以说 Static Import 正是为了解决 Constant Interface Antipattern 而生,但是在使用的时候,却要慎之又慎。如果过度使用,则会导致 namespace 被“污染”,代码难以阅读和维护。试想有 N 个 static import, 你将如何区分 哪个 static member 来自哪个 class?也千万不要使用“*”,把 class 的全部 static member 一股脑给 static import。如果你只是想使用一两个 member,那就分别 static import 吧。
最后以 Static Import 一文的结束语来结束这篇博文:
Used appropriately, static import can make your program more readable, by removing the boilerplate of repetition of class names.