Java的常量接口思考,项目中的常量是放在接口里还是放在类里呢?
最近在看一本书 Java与模式,里面提了一句不建议使用常量接口,甚至举了个java源码的反例,
蛋疼的是没有说为什么?
查了网上一圈发现他们也是知道怎么做而不知道为什么这么做。
然后我只能找谷歌了,翻译后,我把自己理解外加总结的放在下面。
第一
常量类应该是final,不变的,而接口里的参数是final,也是不变的。
那么,看起来接口是放常量没有一定问题,还省去了final的输入,非常的合适。
但是,类是只能单继承的,接口是允许多实现的。
要是类实现的多个接口出现重名的常量,会报错,必须要在实现类明确常量用的是哪个接口的。
虽然这可以说是架构师设计的问题,但是,架构师这么做就违反了依赖倒转原则,这玩意就不细说了。
第二
如果某个实现了常量接口的类被修改不再需要常量了,也会因为序列化兼容原因不得不保持该实现,而且非final类实现常量接口会导致所有子类被污染。
这个应该很少人遇到过,不过这是 Effective Java 里面说的。
具体的理解就是,能被序列化的一定是数据,
那么突然改了数据结构,可能导致老版的数据无法被反序列化,而新版的数据会有冗杂的数据,
要是折腾个几次,网络传输协议 这个无法通过时间或者空间提升的玩意就能逼死你了。
Effective Java 作者 大佬的原话
According to Joshua Bloch, author of "Effective Java":
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.
第三
基于数据只暴露给相应的类的原则,一个类实现一个常量接口,可能只需要其中几个常量,而得到了更多无用的常量,
所以,使用常量接口的时候都是
import static const.valueAAA
那此时和常量类有区别吗?
总结
接口是定义类型的,而不应该用于导出常量。常量接口不建议使用,应使用常量类。