Effective Java 第三版——22. 接口僅用來定義類型


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

Effective Java, Third Edition

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。 這些接口應該被視為不規范的,不應該被效仿。

如果你想導出常量,有幾個合理的選擇方案。 如果常量與現有的類或接口緊密相關,則應將其添加到該類或接口中。 例如,所有數字基本類型的包裝類,如IntegerDouble,都會導出MIN_VALUEMAX_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
}

總之,接口只能用於定義類型。 它們不應該僅用於導出常量。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM