接口只用来定义类型
如果一个类实现了某个接口,那么这个接口类型可以成为指向该类对象的引用。因此类与接口之间的"实现"关系,应该能使用户通过接口了解对象的行为。m88体育 除了这个场景以外,定义接口都是不合适的。违背上述原则的一个反例是常量接口,这样的接口不定义任何方法,仅含有静态final属性,每一个属性都被开放为常量。用户类通过实现这些接口来避免使用常量全名。比如下面的例子:
// Constant interface antipattern - do not use! public interface PhysicalConstants { // Avogadro's number (1/mol) static final double AVOGADROS_NUMBER = 6.02214199e23; // Boltzmann constant (J/K) static final double BOLTZMANN_CONSTANT = 1.3806503e-23; // Mass of the electron (kg) static final double ELECTRON_MASS = 9.10938188e-31; }
m88体育 常量接口是对接口机制的滥用。因为类对常量的使用是一种实现细节,而常量接口会使这些实现细节被泄露到开放的API中。在后续新版本中这些接口必须一直被维护,以保证向下兼容性。一旦某个类实现了常量接口,它所有子类的m88体育名空间都会受到这些常量的污染。
Java标准库中有几个常量接口,比如java.io.ObjectStreamConstants。这些接口应该被视为设计缺陷,开发者不应该模仿它们。
m88体育 正确开放常量的方式有好几种。如果常量与某个类或接口紧密相关,那么应该被直接加入相应的类或接口中。比如,对于封装的数据基本类型Integer或者Double,可以声明MIN_VALUE和MAX_VALUE常量。如果常量可被视作枚举类型的成员,那么他们应该被定义为枚举类型(enum type)。否则,常量应该通过不可实例化的工具类(item 4)来定义。m88体育下面是一个正确定义上述PhysicalConstants的例子:
// Constant utility class package com.effectivejava.science; public class PhysicalConstants { private PhysicalConstants() { } // Prevents instantiation public static final double AVOGADROS_NUMBER = 6.02214199e23; public static final double BOLTZMANN_CONSTANT = 1.3806503e-23; public static final double ELECTRON_MASS = 9.10938188e-31; }
m88体育 通常工具类要求用户使用常量全名,比如:PhysicalConstants.AVOGADROS_NUMBER。如果使用频繁,可以通过静态导入(static import)来简化代码:
// Use of static import to avoid qualifying constants import https://www.mrdaydreamer.com/files/tech/java/static com.effectivejava.science.PhysicalConstants.*; public class Test { double atoms(double mols) { return AVOGADROS_NUMBER * mols; } ... // Many more uses of PhysicalConstants justify static import }
总之,接口必须用来定义类型,而不能用来定义常量。