Tips
《Effective Java, Third Edition》一書英文版已經出版,這本書的第二版想必很多人都讀過,號稱Java四大名著之一,不過第二版2009年出版,到現在已經將近8年的時間,但隨着Java 6,7,8,甚至9的發布,Java語言發生了深刻的變化。
在這里第一時間翻譯成中文版。供大家學習分享之用。

22. 接口僅用來定義類型
當類實現接口時,該接口作為一種類型(type),可以用來引用類的實例。因此,一個類實現了一個接口,因此表明客戶端可以如何處理類的實例。為其他目的定義接口是不合適的。
一種失敗的接口就是所謂的常量接口(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。 這些接口應該被視為不規范的,不應該被效仿。
如果你想導出常量,有幾個合理的選擇方案。 如果常量與現有的類或接口緊密相關,則應將其添加到該類或接口中。 例如,所有數字基本類型的包裝類,如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的數字,無論是整型還是浮點型的,都應該用下划線將數字分成三個數字組,表示一千的正負冪。
通常,實用工具類要求客戶端使用類名來限定常量名,例如PhysicalConstants.AVOGADROS_NUMBER。 如果大量使用實用工具類導出的常量,則通過使用靜態導入來限定具有類名的常量:
// 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
}
總之,接口只能用於定義類型。 它們不應該僅用於導出常量。
