Tips
《Effective Java, Third Edition》一书英文版已经出版,这本书的第二版想必不少人都读过,号称Java四大名著之一,不过第二版2009年出版,到如今已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深入的变化。
在这里第一时间翻译成中文版。供你们学习分享之用。java
当类实现接口时,该接口做为一种类型(type),能够用来引用类的实例。所以,一个类实现了一个接口,所以代表客户端能够如何处理类的实例。为其余目的定义接口是不合适的。electron
一种失败的接口就是所谓的常量接口(constant interface)。 这样的接口不包含任何方法; 它只包含静态final属性,每一个输出一个常量。 使用这些常量的类实现接口,以免须要用类名限定常量名。 这里是一个例子:工具
// Constant interface antipattern - do not use! public interface PhysicalConstants { // Avogadro's number (1/mol) static final double AVOGADROS_NUMBER = 6.022_140_857e23; // Boltzmann constant (J/K) static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; // Mass of the electron (kg) static final double ELECTRON_MASS = 9.109_383_56e-31; }
常量接口模式是对接口的糟糕使用。类在内部使用一些常量,彻底属于实现细节。实现一个常量接口会致使这个实现细节泄漏到类的导出API中。对类的用户来讲,类实现一个常量接口是没有意义的。事实上,它甚至可能使他们感到困惑。更糟糕的是,它表明了一个承诺:若是在未来的版本中修改了类,再也不须要使用常量,那么它仍然必须实现接口,以确保二进制兼容性。若是一个非final类实现了常量接口,那么它的全部子类的命名空间都会被接口中的常量所污染。学习
Java平台类库中有多个常量接口,如java.io.ObjectStreamConstants
。 这些接口应该被视为不规范的,不该该被效仿。atom
若是你想导出常量,有几个合理的选择方案。 若是常量与现有的类或接口紧密相关,则应将其添加到该类或接口中。 例如,全部数字基本类型的包装类,如Integer
和Double
,都会导出MIN_VALUE
和MAX_VALUE
常量。 若是常量最好被看做枚举类型的成员,则应该使用枚举类型(条目 34)导出它们。 不然,你应该用一个不可实例化的工具类来导出常量(条目 4)。 下是前面所示的PhysicalConstants
示例的工具类的版本:翻译
// Constant utility class package com.effectivejava.science; public class PhysicalConstants { private PhysicalConstants() { } // Prevents instantiation public static final double AVOGADROS_NUMBER = 6.022_140_857e23; public static final double BOLTZMANN_CONST = 1.380_648_52e-23; public static final double ELECTRON_MASS = 9.109_383_56e-31; }
顺便提一下,请注意在数字文字中使用下划线字符(_)。 从Java 7开始,合法的下划线对数字字面量的值没有影响,可是若是使用得当的话可使它们更容易阅读。 不管是固定的浮点数,若是他们包含五个或更多的连续数字,考虑将下划线添加到数字字面量中。 对于底数为10的数字,不管是整型仍是浮点型的,都应该用下划线将数字分红三个数字组,表示一千的正负幂。code
一般,实用工具类要求客户端使用类名来限定常量名,例如PhysicalConstants.AVOGADROS_NUMBER
。 若是大量使用实用工具类导出的常量,则经过使用静态导入来限定具备类名的常量:blog
// Use of static import to avoid qualifying constants import static com.effectivejava.science.PhysicalConstants.*; public class Test { double atoms(double mols) { return AVOGADROS_NUMBER * mols; } ... // Many more uses of PhysicalConstants justify static import }
总之,接口只能用于定义类型。 它们不该该仅用于导出常量。接口