読者です 読者をやめる 読者になる 読者になる

【Effective Java】項目19:型を定義するためだけにインタフェースを利用する

インタフェースは、その実装クラスのインスタンスで何ができるかだけを述べるべきである。 その他の目的、たとえば定数インタフェースなどには利用しない。

定数インタフェース

メソッドを持たず、static final の定数を外部に提供しているだけのインタフェースを定数インタフェースと呼ぶ。

// 定数インタフェース
public interface PhysicalConstants {
    // アボガドロ定数(1/mol)
    static final double AVOGADROS_NUMBER = 6.02214199e23;
    // ボルツマン定数(J/K)
    static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    // 電子の質量(kg)
    static final double ELECTRON_MASS = 9.10938188e-31;
}

このようなインタフェースの使い方は推奨されない。

定数インタフェースを使うと、このインタフェースを実装することで特定の定数が利用できるようになる。 ただし、こうすると実装の詳細を、インタフェース側にもたせることになってしまう。

Java ライブラリには java.io.ObjectStreamConstatns などの定数インタフェースが存在するが、これはまねするべきではない。

代替手段

定数を外部に公開したい場合は、enum 型(項目30)か、インスタンス不可能なユティリティクラス(項目4)で提供するべきである。

以下は、PhysicalConstants の定数ユティリティクラス版である。

// 定数ユティリティクラス 
public class PhysicalConstants {
     // インスタンス化を防ぎ、継承できないようにする
    private PhysicalConstants() {}

    // アボガドロ定数(1/mol)
    static final double AVOGADROS_NUMBER = 6.02214199e23;
    // ボルツマン定数(J/K)
    static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    // 電子の質量(kg)
    static final double ELECTRON_MASS = 9.10938188e-31;
}

ユティリティクラス版の PhysicalConstants は、クラス名で定数を修飾する必要がある。 ただし、Java 1.5 からは、static インポート機能を利用するとクラス名を省略できるようになる。

import static com.hoge.PhysicalConstants.*;

public class Main {
    public static void main(String[] args) {
        // PhysicalConstants 修飾を省略する
        double constant = AVOGADROS_NUMBER;
        System.out.println(constant);
    }

感想

下記のコードを手元の IntelliJ IDEA で検証してたら、警告がでた。

public interface PhysicalConstants {
    // アボガドロ定数(1/mol)
    static final double AVOGADROS_NUMBER = 6.02214199e23;
    // ボルツマン定数(J/K)
    static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
    // 電子の質量(kg)
    static final double ELECTRON_MASS = 9.10938188e-31;
}

警告は以下の通り。

Modifier 'static' is redundant for interface filed.

Modifier 'final' is redundant for interface filed.

どうやら、static と final はいらないらしい。仕様を確認したら明記してあった。

9.3. Field (Constant) Declarations

Every field declaration in the body of an interface is implicitly public, static, and final. It is permitted to redundantly specify any or all of these modifiers for such fields.

あっさりとした項目でした。めでたし、めでたし。